Son of the Inventory App
description
Transcript of Son of the Inventory App
Son of the Inventory AppSon of the Inventory App
But firstBut first
The question came up about how to run a production server with Rails…
The question came up about how to run a production server with Rails…
Three PossibilitiesThree Possibilities
Use fastcgi and apache Use apache as a proxy server, against a
cluster of mongrel servers (this is covered in Agile Web Development with Rails)
And the one you want, passenger:http://www.modrails.com/
I'm still playing with this, more to come…
Use fastcgi and apache Use apache as a proxy server, against a
cluster of mongrel servers (this is covered in Agile Web Development with Rails)
And the one you want, passenger:http://www.modrails.com/
I'm still playing with this, more to come…
InstallationInstallation
It's a gem so use "sudo gem install passenger"
Then run:sudo passenger-install-apache2-module
This will install the modules needed
It's a gem so use "sudo gem install passenger"
Then run:sudo passenger-install-apache2-module
This will install the modules needed
Migrate to productionMigrate to production
rake migrate RAILS_ENV=production This will create a new empty database for
a production server You can copy your development db over
the production one if you want to carry your test data over, or dump and load the data
rake migrate RAILS_ENV=production This will create a new empty database for
a production server You can copy your development db over
the production one if you want to carry your test data over, or dump and load the data
ConfigurationConfiguration
In the apache config file, check to make sure you have the modules loading
I had to add these manually on my laptop
In the apache config file, check to make sure you have the modules loading
I had to add these manually on my laptop
LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/ gems/passenger-2.0.3/ext/apache2/mod_passenger.sogems/passenger-2.0.3/ext/apache2/mod_passenger.so
# Passenger config# Passenger configPassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-2.0.3PassengerRuby /usr/local/bin/rubyPassengerRuby /usr/local/bin/ruby
Virtual HostVirtual Host
You need to define a virtual host This is what I’m using for now Note that I’m using podzone.net, this is dyndns The base uri should point to a soft link to your application's public folder--
doesn't work for me
You need to define a virtual host This is what I’m using for now Note that I’m using podzone.net, this is dyndns The base uri should point to a soft link to your application's public folder--
doesn't work for me
<VirtualHost *:80><VirtualHost *:80> ServerAdmin [email protected] [email protected] DocumentRoot /Library/WebServer/DocumentsDocumentRoot /Library/WebServer/Documents RailsBaseURI /inventoryRailsBaseURI /inventory RailsSpawnMethod conservativeRailsSpawnMethod conservative ServerName avatar.podzone.netServerName avatar.podzone.net</VirtualHost></VirtualHost>
Odds and EndsOdds and Ends
After configuring the web server, restart it:sudo apachectl graceful
Watch your logs:tail -f /var/log/httpd/error_log
After configuring the web server, restart it:sudo apachectl graceful
Watch your logs:tail -f /var/log/httpd/error_log
Tonight and Next WeekTonight and Next Week
Tonight time and date tags lots searches
Next Week more searches email filesystem access ?
Tonight time and date tags lots searches
Next Week more searches email filesystem access ?
When we left our applicationWhen we left our application
A database backend Some Migrations Played with Types Played with Time Methods Some Validations
A database backend Some Migrations Played with Types Played with Time Methods Some Validations
Let's take a look at the sourceLet's take a look at the source
Model Controller Views
Model Controller Views
Next StepsNext Steps
Refine status options Refine date_submitted Add searches
Refine status options Refine date_submitted Add searches
StatusStatus
We can't depend on the user to type what we want
So we need to define what statuses we'll accept ordered, delivered, deployed
Provide a controlled method for selection Radio buttons
We can't depend on the user to type what we want
So we need to define what statuses we'll accept ordered, delivered, deployed
Provide a controlled method for selection Radio buttons
new.html.erbnew.html.erb
In the views/machine dir, we need to edit new.html.erb file
This one's easy, note we're setting a default
In the views/machine dir, we need to edit new.html.erb file
This one's easy, note we're setting a default
<p><p> <%= f.label :status %><br /><%= f.label :status %><br /> <%= f.radio_button :status, "ordered", :checked => true %><%= f.radio_button :status, "ordered", :checked => true %> Ordered <br/>Ordered <br/> <%= f.radio_button :status, "delivered" %>Delivered <br/><%= f.radio_button :status, "delivered" %>Delivered <br/> <%= f.radio_button :status, "deployed" %>Deployed <br/><%= f.radio_button :status, "deployed" %>Deployed <br/> </p></p>
edit.html.erbedit.html.erb
For the edit view, the same thing without the default
For the edit view, the same thing without the default
<p><p> <%= f.label :status %><br /><%= f.label :status %><br /> <%= f.radio_button :status, "ordered" %>Ordered <br/><%= f.radio_button :status, "ordered" %>Ordered <br/> <%= f.radio_button :status, "delivered" %>Delivered <br/><%= f.radio_button :status, "delivered" %>Delivered <br/> <%= f.radio_button :status, "deployed" %>Deployed <br/><%= f.radio_button :status, "deployed" %>Deployed <br/> </p></p>
A validationA validation
We might not need it, but jic Note the use of %w
We might not need it, but jic Note the use of %w
Check status for a valid choiceCheck status for a valid choice validates_inclusion_of \validates_inclusion_of \ :status, \:status, \ :in => %w(ordered delivered deployed), \:in => %w(ordered delivered deployed), \ :message => "Status must be ordered, delivered, or deployed":message => "Status must be ordered, delivered, or deployed"
date_submitteddate_submitted
The date_submitted is just too precise--we don't need the time values, just the date
We're using datetime_select, but time and date methods?
The date_submitted is just too precise--we don't need the time values, just the date
We're using datetime_select, but time and date methods?
date_selectdate_select datetime_selectdatetime_select distance_of_time_in_wordsdistance_of_time_in_words distance_of_time_in_words_to_nowdistance_of_time_in_words_to_now select_dateselect_date select_datetimeselect_datetime select_dayselect_day select_hourselect_hour select_minuteselect_minute select_monthselect_month select_secondselect_second select_timeselect_time select_yearselect_year time_ago_in_wordstime_ago_in_words time_selecttime_select
What's the difference?What's the difference?
date_select, datetime_select, select_time generate inputs tied to an object in the model
select_date, select_datetime, select_day, select_hour, select_minute, select_month, select_second, select_time, select_year produce inputs, but these are not tied to an object in the model
distance_of_time_in_words, distance_of_time_in_words_from_now, time_ago_in_words calculate intervals
This distinction between methods tied to the model and those which are not is pervasive
date_select, datetime_select, select_time generate inputs tied to an object in the model
select_date, select_datetime, select_day, select_hour, select_minute, select_month, select_second, select_time, select_year produce inputs, but these are not tied to an object in the model
distance_of_time_in_words, distance_of_time_in_words_from_now, time_ago_in_words calculate intervals
This distinction between methods tied to the model and those which are not is pervasive
date_selectdate_select
date_select give us an input for just the date
Lots of options
date_select give us an input for just the date
Lots of options
<p><p> <%= f.label :date_submitted %><br /><%= f.label :date_submitted %><br /> <%= f.date_select \<%= f.date_select \ :date_submitted, \:date_submitted, \ :order => [:month, :day, :year], \:order => [:month, :day, :year], \ :start_year => 2008 %>:start_year => 2008 %> </p></p>
Another ValidationAnother Validation
We should also refine the date_submitted validation
We don't allow selection in the past, but we should allow that for at least a week or so in the past
We should limit the future as well
We should also refine the date_submitted validation
We don't allow selection in the past, but we should allow that for at least a week or so in the past
We should limit the future as well
First Try: 1 day ago and ErrFirst Try: 1 day ago and Err This validates that the date and time are reasonable values def date_submitted_must_be_sensible errors.add(:date_submitted, \ 'Time and date cannot be in the past')\ if date_submitted < 3600.mins.ago This one is too restrictive if date_submitted < Time.now errors.add(:date_submitted, \ 'Time and date cannot be more than 2 years in the future')\ if date_submitted > Time.now.advance(:years => 2) is equivalent to: #if date_submitted > 2.years.from_now end
This WorksThis Works # This validates that the date and time are resonable values# This validates that the date and time are resonable values def date_submitted_must_be_sensible def date_submitted_must_be_sensible errors.add(:date_submitted, \errors.add(:date_submitted, \ 'Time and date cannot be more than 2 months in the past')\'Time and date cannot be more than 2 months in the past')\ if date_submitted < 2.months.agoif date_submitted < 2.months.ago # This one is too restrictive# This one is too restrictive # if date_submitted < Time.now# if date_submitted < Time.now errors.add(:date_submitted, \errors.add(:date_submitted, \ 'Time and date cannot be more than 2 years in the future')\'Time and date cannot be more than 2 years in the future')\ if date_submitted > Time.now.advance(:years => 2)if date_submitted > Time.now.advance(:years => 2) # is equivalent to:# is equivalent to: #if date_submitted > 2.years.from_now#if date_submitted > 2.years.from_now end end
Refining Date AppearanceRefining Date Appearance
The inputs are good, but the display leaves a bit to be desired…
The inputs are good, but the display leaves a bit to be desired…
QuickTime™ and a decompressor
are needed to see this picture.
Using strftimeUsing strftime
strftime is a method that will format a datetime object in custom format
The way it works is you call the method with a string that represents the format you want
The % sigil represents a time or date symbol
strftime is a method that will format a datetime object in custom format
The way it works is you call the method with a string that represents the format you want
The % sigil represents a time or date symbol
<p><p> <b>Date submitted:</b><b>Date submitted:</b> <%=h @machine.date_submitted.strftime "%m-%d-%Y" %><%=h @machine.date_submitted.strftime "%m-%d-%Y" %></p></p>
strftime formattingstrftime formatting
Lots of options
There are a few more
I think all of these work with rails
Lots of options
There are a few more
I think all of these work with rails
%a - abbreviated weekday name according to the current locale%a - abbreviated weekday name according to the current locale %A - full weekday name according to the current locale%A - full weekday name according to the current locale %b - abbreviated month name according to the current locale%b - abbreviated month name according to the current locale %B - full month name according to the current locale%B - full month name according to the current locale %c - preferred date and time representation for the current locale%c - preferred date and time representation for the current locale %C - century number (the year divided by 100 and truncated to an integer)%C - century number (the year divided by 100 and truncated to an integer) %d - day of the month as a decimal number (range 01 to 31)%d - day of the month as a decimal number (range 01 to 31) %D - same as %m/%d/%y%D - same as %m/%d/%y %e - day of the month as a decimal number%e - day of the month as a decimal number %g - like %G, but without the century.%g - like %G, but without the century. %H - hour as a decimal number using a 24-hour clock (range 00 to 23)%H - hour as a decimal number using a 24-hour clock (range 00 to 23) %I - hour as a decimal number using a 12-hour clock (range 01 to 12)%I - hour as a decimal number using a 12-hour clock (range 01 to 12) %j - day of the year as a decimal number (range 001 to 366)%j - day of the year as a decimal number (range 001 to 366) %m - month as a decimal number (range 01 to 12)%m - month as a decimal number (range 01 to 12) %M - minute as a decimal number%M - minute as a decimal number %n - newline character%n - newline character %p - either `am' or `pm' according to the given time value%p - either `am' or `pm' according to the given time value %r - time in a.m. and p.m. notation%r - time in a.m. and p.m. notation %R - time in 24 hour notation%R - time in 24 hour notation %S - second as a decimal number%S - second as a decimal number %t - tab character%t - tab character %T - current time, equal to %H:%M:%S%T - current time, equal to %H:%M:%S %u - weekday as a decimal number [1,7], with 1 representing Monday%u - weekday as a decimal number [1,7], with 1 representing Monday
from http://us.php.net/strftime
Refining our indexRefining our index
Currently, the index.html.erb file returns all of the records, by virtue of @machines = Machine.find(:all)
We don't really want that, since any records exported to the main db are not longer relevant @machines = Machine.find(\ :all, \ :conditions => { :exported_to_main => false})
Currently, the index.html.erb file returns all of the records, by virtue of @machines = Machine.find(:all)
We don't really want that, since any records exported to the main db are not longer relevant @machines = Machine.find(\ :all, \ :conditions => { :exported_to_main => false})
SearchesSearches
At this point, we have a pretty nice app But we don't have a search tool We'll want a simple search for the main
page Also an advanced search page with more
options
At this point, we have a pretty nice app But we don't have a search tool We'll want a simple search for the main
page Also an advanced search page with more
options
Simple SearchSimple Search
For this we'll use a find method We'll need an if statement in the controller We'll also need an input on the
index.html.erb file To get started, we'll just search for a name
match
For this we'll use a find method We'll need an if statement in the controller We'll also need an input on the
index.html.erb file To get started, we'll just search for a name
match
The inputThe input
So far, the inputs we have are all associated with objects in the model
We don't need a db entry tho Use an input not linked to the model,
text_field_tag Inputs independent of the model end in
_tag by convention
So far, the inputs we have are all associated with objects in the model
We don't need a db entry tho Use an input not linked to the model,
text_field_tag Inputs independent of the model end in
_tag by convention
The InputThe Input
Here's the input Note the use of the params hash Also that the name of the submit_tag is nil This will default to a get
Here's the input Note the use of the params hash Also that the name of the submit_tag is nil This will default to a get
<p><p> <%= text_field_tag :general_search, params[:search] %><%= text_field_tag :general_search, params[:search] %> <%= submit_tag "General Search", :name => nil %><%= submit_tag "General Search", :name => nil %> </p></p>
An if to catch the searchAn if to catch the search
We need to check if we have the get var Then we set @machines to be the result of a find Here, the find just looks for a match between the
data passed via the get into the params hash and the user_name object in the model…
We need to check if we have the get var Then we set @machines to be the result of a find Here, the find just looks for a match between the
data passed via the get into the params hash and the user_name object in the model…
if params[:general_search]if params[:general_search] @machines = Machine.find(\@machines = Machine.find(\ :all, \:all, \ :conditions => [ "user_name = ?", params[:general_search] ]):conditions => [ "user_name = ?", params[:general_search] ]) endend
findfind
Conditions can be used as a string, array or hash
If you use strings, you should sanitize
Conditions can be used as a string, array or hash
If you use strings, you should sanitize
def self.authenticate_unsafely(user_name, password)def self.authenticate_unsafely(user_name, password) find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'")find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'")endenddef self.authenticate_safely(user_name, password)def self.authenticate_safely(user_name, password) find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ])find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ])endenddef self.authenticate_safely_simply(user_name, password)def self.authenticate_safely_simply(user_name, password) find(:first, :conditions => { :user_name => user_name, :password => password })find(:first, :conditions => { :user_name => user_name, :password => password })endend
http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M001696http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M001696
find_by_sql()find_by_sql()
You can also use sql with the find_by_sql method This does tie you to the db backend
You can also use sql with the find_by_sql method This does tie you to the db backend
http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M001696http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M001696
# A simple SQL query spanning multiple tables Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id" > [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
Refining a findRefining a find
Here, we're using an array with Ors to search the basic text fields
Here, we're using an array with Ors to search the basic text fields
if params[:general_search] #@target = params[:general_search] @machines = Machine.find(:all, \ :conditions => [ \ "user_name = ? OR \ from_entity = ? OR \ from_location = ? OR \ to_entity = ? OR \ to_location = ?", \ params[:general_search], params[:general_search], params[:general_search], params[:general_search], params[:general_search] ]) end
Combining codeCombining code
Right now, this works because we're setting @machines first with a find that looks for records not exported to main, and then reset it if general_search is set in params
This is sloppy, we should combine them So move the first find to an else
Right now, this works because we're setting @machines first with a find that looks for records not exported to main, and then reset it if general_search is set in params
This is sloppy, we should combine them So move the first find to an else
if params[:general_search] @machines = Machine.find(:all, \ :conditions => [ "user_name = ? OR from_entity = ? OR from_location = ? OR to_entity = ? OR to_location = ?", params[:general_search], params[:general_search], params[:general_search], params[:general_search], params[:general_search] ]) else @machines = Machine.find( \ :all, \ :conditions => { :exported_to_main => false}) end
One more thingOne more thing
Our search so far will only find exact matches
We can use a LIKE condition
Notice the use of % and #{}
Our search so far will only find exact matches
We can use a LIKE condition
Notice the use of % and #{}
:conditions => [:conditions => [ "user_name LIKE ? OR "user_name LIKE ? OR from_entity LIKE ? OR from_entity LIKE ? OR from_location LIKE ? OR from_location LIKE ? OR to_entity LIKE ? OR to_entity LIKE ? OR to_location LIKE ?", to_location LIKE ?", "%#{params[:general_search]}%","%#{params[:general_search]}%", "%#{params[:general_search]}%","%#{params[:general_search]}%", "%#{params[:general_search]}%","%#{params[:general_search]}%", "%#{params[:general_search]}%","%#{params[:general_search]}%", "%#{params[:general_search]}%" ])"%#{params[:general_search]}%" ])
Advanced SearchAdvanced Search
We could probably do this with just a new view
But for grins, we'll create a new controller named search with an index page:
ruby script/generate controller search index
We could probably do this with just a new view
But for grins, we'll create a new controller named search with an index page:
ruby script/generate controller search index
A simple pageA simple page
Just to be able to test things out, we'll make a new page, ordered.html.erb in the views/search dir (which was created when we generated the controller)
This will just display some simple results, since we're just testing…
Just to be able to test things out, we'll make a new page, ordered.html.erb in the views/search dir (which was created when we generated the controller)
This will just display some simple results, since we're just testing…
ordered.html.erbordered.html.erb<h1>Ordered Machines</h1><h1>Ordered Machines</h1>
<% for machine in @machines -%> <% for machine in @machines -%> <%=h machine.user_name %><br/><%=h machine.user_name %><br/> <%=h machine.date_submitted.strftime "%m-%d-%Y" %><br/> <%=h machine.date_submitted.strftime "%m-%d-%Y" %><br/> Ticket: <%=h machine.ticket_number %><br/>Ticket: <%=h machine.ticket_number %><br/> From: <%=h machine.from_entity %>From: <%=h machine.from_entity %> To: <%=h machine.to_entity %><br/>To: <%=h machine.to_entity %><br/> <%=h machine.comments %><br/><%=h machine.comments %><br/> <hr/><hr/> <% end %> <% end %>
Try to load itTry to load it
If we load the page using:http://127.0.0.1:3000/search/ordered
we get an error, no method This is because our new controller has no
methods defined
If we load the page using:http://127.0.0.1:3000/search/ordered
we get an error, no method This is because our new controller has no
methods defined
a better finda better find
find as a method is handy, but it's limited For rails 1x, Nick Kallen wrote a plugin,
has_finder, which extended searches This functionality was incorporated into
rails 2.x as named_scope A class method, this will create a custom
method with search conditions
find as a method is handy, but it's limited For rails 1x, Nick Kallen wrote a plugin,
has_finder, which extended searches This functionality was incorporated into
rails 2.x as named_scope A class method, this will create a custom
method with search conditions
machine.erbmachine.erb
In the machine controller, we can create a named scope that finds machines that have been ordered
We can then call this from the search controller We'll do more with named_scope next week--it's
more flexible than find but also a bit confusing
In the machine controller, we can create a named scope that finds machines that have been ordered
We can then call this from the search controller We'll do more with named_scope next week--it's
more flexible than find but also a bit confusing
# Using named_scope, define a search that returns # records of machines that have been ordered named_scope :machines_ordered, :conditions => { :status => "ordered" }
search.erbsearch.erb
In the search controller, we then set a variable
So when we load /search/ordered, the search controller accesses the method we defined in the machine controller, and passes the data to ordered.html.erb
In the search controller, we then set a variable
So when we load /search/ordered, the search controller accesses the method we defined in the machine controller, and passes the data to ordered.html.erb
# This structure accesses a named scope # in machines_controller.erb @machines = Machine.machines_ordered
Ok?Ok?
Yes, this is ok, but if we follow this approach through, we'll wind up with many pages
What would be better would be to use the search/index.html.erb file to allow selection, and then pass the data into the machine/index.html.erb file
So we start with the search/index.html.erb file And we'll start with find…
Yes, this is ok, but if we follow this approach through, we'll wind up with many pages
What would be better would be to use the search/index.html.erb file to allow selection, and then pass the data into the machine/index.html.erb file
So we start with the search/index.html.erb file And we'll start with find…
<h2>Advanced Search</h2><h2>Advanced Search</h2><h3>Choose Field</h3><h3>Choose Field</h3><% form_tag machines_path, :method => 'get' do %><% form_tag machines_path, :method => 'get' do %> <p><p> <%= text_field_tag :search_target, params[:search] %> for<%= text_field_tag :search_target, params[:search] %> for <%= text_field_tag :search_string, params[:search] %><%= text_field_tag :search_string, params[:search] %> <%= submit_tag "Search", :name => nil %><%= submit_tag "Search", :name => nil %> </p></p><% end %><% end %>
search/index.html.erbsearch/index.html.erb
Some text_field_tags and Some text_field_tags and
search/index.html.erbsearch/index.html.erb
This gives us a simple form, for which we enter the field to search and the string to search for
This gives us a simple form, for which we enter the field to search and the string to search for
QuickTime™ and a decompressor
are needed to see this picture.
machine controllermachine controller
Add an if to the controller, this time we'll use a find with slightly different syntax
Add an if to the controller, this time we'll use a find with slightly different syntax
@machines = Machine.find(@machines = Machine.find( :all, :all, :conditions => { params[:search_target] => params[:search_string]}:conditions => { params[:search_target] => params[:search_string]} ) if params[:search_target]) if params[:search_target]
A basic working searchA basic working search
So we have a basic form that has some flexibility for searches
Everything up to this point is in inventory02.gz.tar up in the samples dir
So we have a basic form that has some flexibility for searches
Everything up to this point is in inventory02.gz.tar up in the samples dir
A selectionA selection
What we have works, but it's awkward For our advanced search we need a select We'll start with an html select
What we have works, but it's awkward For our advanced search we need a select We'll start with an html select
<select name="search_target"><select name="search_target"> <option value="user_name">User Name</option><option value="user_name">User Name</option> <option value="from_entity">From Entity</option><option value="from_entity">From Entity</option> <option value="from_location">From Location</option><option value="from_location">From Location</option> <option value="to_entity">To Entity</option> <option value="to_entity">To Entity</option> <option value="to_location">To Location</option> <option value="to_location">To Location</option> </select></select>
select_tagselect_tag
But there's a select_tag we can use, and it has lots of options
A simple use, that's hard coded
But there's a select_tag we can use, and it has lots of options
A simple use, that's hard coded
<%= select_tag "search_target", <%= select_tag "search_target", options_for_select([ "user_name", "from_entity", options_for_select([ "user_name", "from_entity", "from_location" ]) %>"from_location" ]) %>
select_tagselect_tag
select_tag can also take arrays and hashes as parameters
We don't want to have to put data in the views So we can define a constant in the machine.rb file and
call that into the select_tag thusly:
select_tag can also take arrays and hashes as parameters
We don't want to have to put data in the views So we can define a constant in the machine.rb file and
call that into the select_tag thusly:
<%= select_tag "search_target", <%= select_tag "search_target", options_for_select(Machine::CATEGORIES, options_for_select(Machine::CATEGORIES, :multiple => true) %>:multiple => true) %>
Our constantOur constant
In a new data section of the machine.rb file Now we have a user friendly pop up and a
central location for the data
In a new data section of the machine.rb file Now we have a user friendly pop up and a
central location for the data
CATEGORIES=CATEGORIES= {{ 'User Name' => 'user_name', 'User Name' => 'user_name', 'From Entity' => 'from_entity', 'From Entity' => 'from_entity', 'From Location' => 'from_location','From Location' => 'from_location', 'To Entity' => 'to_entity','To Entity' => 'to_entity', 'To Location' => 'to_location''To Location' => 'to_location' }}
So far so goodSo far so good
But this again depends on exact matches And this is in a hash structure--according
to the docs, you can use a LIKE in a hash
But this again depends on exact matches And this is in a hash structure--according
to the docs, you can use a LIKE in a hash
@machines = Machine.find(@machines = Machine.find( :all, :all, :conditions => { params[:search_target] => :conditions => { params[:search_target] => params[:search_string]}params[:search_string]} ) if params[:search_target]) if params[:search_target]
Changed to an ArrayChanged to an Array
This change is easy Notice the if, that keeps this one from
interfering with the general search
This change is easy Notice the if, that keeps this one from
interfering with the general search
# Array structure, can use LIKE# Array structure, can use LIKE @machines = Machine.find(@machines = Machine.find( :all, :all, :conditions => [ "#{params[:search_target]} LIKE ?", :conditions => [ "#{params[:search_target]} LIKE ?", params[:search_string] ]params[:search_string] ] ) if params[:search_target]) if params[:search_target]
Controller vs ModelController vs Model
This search is all in the controller Ideally, we'd want the model to do the
heavy lifting One stop shopping Write once, use anywhere
So, we define a method in the model
This search is all in the controller Ideally, we'd want the model to do the
heavy lifting One stop shopping Write once, use anywhere
So, we define a method in the model
def self.search_string(target, string)def self.search_string(target, string) find(:all, :conditions => [ "#{target} LIKE ?", "%#{string}%" ]) find(:all, :conditions => [ "#{target} LIKE ?", "%#{string}%" ]) endend
Call Method from ControllerCall Method from Controller
And we can call this from the controller And we can call this from the controller
@machines = Machine.search_string(params[:search_target], params[:search_string]) if params[:search_target]
Back to our general searchBack to our general search
We've stuck that in the controller, too So move that into the model This one's longer, but the idea is the same
We've stuck that in the controller, too So move that into the model This one's longer, but the idea is the same
def self.general_search(search)def self.general_search(search) if searchif search find(:all,find(:all, :conditions => [:conditions => [ "user_name LIKE ? OR "user_name LIKE ? OR from_entity LIKE ? OR from_entity LIKE ? OR from_location LIKE ? OR from_location LIKE ? OR to_entity LIKE ? OR to_entity LIKE ? OR to_location LIKE ?", to_location LIKE ?", "%#{search}%","%#{search}%", "%#{search}%","%#{search}%", "%#{search}%","%#{search}%", "%#{search}%","%#{search}%", "%#{search}%" ])"%#{search}%" ]) elseelse find(:all, :conditions => { :exported_to_main => false})find(:all, :conditions => { :exported_to_main => false}) endend endend
SourcesSources
http://primevector.wordpress.com/2007/10/02/radio-button-info-for-ruby-on-rails/
http://shiningthrough.co.uk/blog/show/6 http://railscasts.com/episodes/37-simple-s
earch-form http://railscasts.com/episodes/108-named-
scope
http://primevector.wordpress.com/2007/10/02/radio-button-info-for-ruby-on-rails/
http://shiningthrough.co.uk/blog/show/6 http://railscasts.com/episodes/37-simple-s
earch-form http://railscasts.com/episodes/108-named-
scope