I am very new to Rails and Web-programming and hope you can help me out with my very first project.
I am developing a website for a Real Estate Agency.
I have 3 tables in my database (Homes: Home_ID, Home_Name, Admin_ID; Admins: Admin_ID, Admin_Name, Admin_Email; Images: Image_ID, Image_Path, Image_Name, Home_ID, Admin_ID).
All 3 tables have been created using scaffold. The image information (name, path, image_id, home_id etc) have been entered in SQLite.
I get all text information of the different houses displayed correctly on the website except the pictures.
My attempt to link it in the view/home/index.html.erb created the following error:
undefined method `image_path' for #<Home:0xb63d85e0>
I used below code:
<% #homes.each do |home| %>
<tr>
<td><%= home.name %></td>
<td><%= home.details %></td>
<td><%= home.region %></td>
<td><%= home.address %></td>
<td><%= home.price %></td>
<td><%= home.admin_id %></td>
<td><%= home.image_path %></td>
</tr>
<% end %>
</table>
It looks like that the data entered in SQLite do not sync with rails.
Do you have any idea what I have done wrong and how I can fix it?
Thank you.
I'm not positive what the relationship would be between your images and home models would be so correct me if I'm wrong, but I'm guessing that homes will have many images. Each image would belong to one home. Is this correct? If so, you will need to declare that in your models like so:
models/home.rb
has_many :images
models/image.rb
belongs_to :home
You will then need to add this to the image database:
t.integer "home_id"
You can add it by going to the command line and typing:
rails g migration AddHomeToImages home_id:integer
You should look in db/migrate/ and then the most recent migration file and make sure it looks like this:
add_column :images, :home_id, :integer
Then run:
rake db:migrate
At this point you'll only need to update your controller and views to show this association. Let me know if this helps and if so I'll help you with your controller and views.
What's happening is that you are looping through a selection of records from the Home table. Because of this, when you call
<td><%= home.image_path %></td>
it's not recognizing the attribute image_path because you don't have image_path as a column of Home table. You only have Home_ID, Home_Name, Admin_ID for your columns. You will have to look into associations between models in order to figure out how to grab the image_path for each home record. You can start here.
If you update the code later on I'll be glad to comment on it.
I think that the best solution here will be to use paperclip gem.
You can take a look at this very old railscast eoisode just to understand how it works:
http://railscasts.com/episodes/134-paperclip
And here is github repository:
https://github.com/thoughtbot/paperclip
Paperclip will help you with paths, styles and preview for your images.
Thanks Jason,
I agree that it is a bit big for newbies, but the requirements were that we do a website where we need to read and write from/to a database. We had a quick introduction to rails with partnerwork and are now on our own and a "bit" lost and running out of time.
Here is the error message I am getting:
NameError in Homes#index
undefined local variable or method `image' for
<#:0xb62f7aa4>
Extracted source (around line #20):
17: <% #homes.each do |home| %>
18: <tr>
19: <td><%= home.name %></td>
20: <td><%= image.home_id %></td>
21: <td><%= home.details %></td>
22: <td><%= home.region %></td>
23: <td><%= home.address %></td>
When I create the database tables I had an Image_ID in the homes table, but I was told that I don`t need it and that it is enough to have only Home_ID in the images table.
I understand that the error is caused because of image.home_id.
What is your opinion? Should I add the Image_ID back to the homes table in order to display all images for the respective home_id or is there another way? I would like to be able to decide which picture will be displayed as the main picture and which ones as the smaller pictures.
Here is the code I use:
models/home.rb
class Home < ActiveRecord::Base
attr_accessible :address, :admin_id, :details, :name, :price, :region
has_many :images
end
models/image.rb
class Image < ActiveRecord::Base
attr_accessible :image_description, :image_name, :image_path
belongs_to :home
end
views/homes/index.html.erb
<h1>Listing homes</h1>
<table>
<tr>
<th>Name</th>
<th>Image</th>
<th>Details</th>
<th>Region</th>
<th>Address</th>
<th>Price</th>
<th>Admin</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #homes.each do |home| %>
<tr>
<td><%= home.name %></td>
<td><%= image.home_id %></td>
<td><%= home.details %></td>
<td><%= home.region %></td>
<td><%= home.address %></td>
<td><%= home.price %></td>
<td><%= home.admin_id %></td>
<td><%= link_to 'Show', home %></td>
<td><%= link_to 'Edit', edit_home_path(home) %></td>
<td><%= link_to 'Destroy', home, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Home', new_home_path %>
views/homes/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= #home.name %>
</p>
<p>
<b>Image:</b>
<%= #image.home_id %>
</p>
<p>
<b>Details:</b>
<%= #home.details %>
</p>
<p>
<b>Region:</b>
<%= #home.region %>
</p>
<p>
<b>Address:</b>
<%= #home.address %>
</p>
<p>
<b>Price:</b>
<%= #home.price %>
</p>
<p>
<b>Admin:</b>
<%= #home.admin_id %>
</p>
<%= link_to 'Edit', edit_home_path(#home) %> |
<%= link_to 'Back', homes_path %>
views/images/_form.html.erb
<%= form_for(#image) do |f| %>
<% if #image.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#image.errors.count, "error") %> prohibited this image from being saved:</h2>
<ul>
<% #image.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :image_name %><br />
<%= f.text_field :image_name %>
</div>
<div class="field">
<%= f.label :image_path %><br />
<%= f.text_field :image_path %>
</div>
<div class="field">
<%= f.label :image_description %><br />
<%= f.text_area :image_description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
controllers/images_controller.rb
class ImagesController < ApplicationController
# GET /images
# GET /images.json
def index
#images = Image.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #images }
end
end
# GET /images/1
# GET /images/1.json
def show
#image = Image.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #image }
end
end
# GET /images/new
# GET /images/new.json
def new
#image = Image.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #image }
end
end
# GET /images/1/edit
def edit
#image = Image.find(params[:id])
end
# POST /images
# POST /images.json
def create
#image = Image.new(params[:image])
respond_to do |format|
if #image.save
format.html { redirect_to #image, notice: 'Image was successfully created.' }
format.json { render json: #image, status: :created, location: #image }
else
format.html { render action: "new" }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# PUT /images/1
# PUT /images/1.json
def update
#image = Image.find(params[:id])
respond_to do |format|
if #image.update_attributes(params[:image])
format.html { redirect_to #image, notice: 'Image was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
# DELETE /images/1
# DELETE /images/1.json
def destroy
#image = Image.find(params[:id])
#image.destroy
respond_to do |format|
format.html { redirect_to images_url }
format.json { head :no_content }
end
end
end
Thank you so much. I really appreciate your help!!!
Related
so i have installed best in place gem in a rails 4 environment and initialised it correctly. (i can click on the name field and the box becomes editable).
I've this code in my admin_namespaced user controller
class Admin::UsersController < Admin::BaseController
def index
#users = User.all
# #columns = User.column_names
end
def show
#user = User.find(params[:id])
end
def update
#user = User.find params[:id]
respond_to do |format|
if #user.update_attributes(user_params)
format.html { redirect_to(user, :notice => 'User was successfully updated.') }
format.json { respond_with_bip(#user) }
else
format.html { render :action => "index" }
format.json { respond_with_bip(#user) }
end
end
end
private
def user_params
params.require(:user).permit(:name,:email,:password,:password_confirmation)
end
end
and basically i want to use it in conjuction with rails datatables gem that i successfully setup, to inline-edit corresponding fields.
this is the html.erb code in my user index view
<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= link_to "Back", admin_path %>
<table class="display responsive no-wrap text-center" id="usertableadmin">
<thead>
<tr>
<th>id</th>
<th>Username</th>
<th>Email</th>
<th>Activated?</th>
<th>Admin?</th>
</tr>
</thead>
<tbody>
<% #users.each do |user| %>
<tr>
<td><%= user.id %></td>
<td><%= best_in_place user, :name%></td>
<td><%= user.email %></td>
<td><%= user.activated %></td>
<td><%= user.admin %></td>
</tr>
<% end %>
</tbody>
</table>
here is what the html code looks like on the tag that has the best_in_place initialization.
<span data-bip-type="input" data-bip-attribute="name" data-bip-object="user" data-bip-original-content="Example User" data-bip-url="/users/1" data-bip-value="Example User" class="best_in_place" id="best_in_place_user_1_name">Example User</span>
I dont know for sure but for some reason the fields do not get updated. When i click to change the name it gets reverted to the previous one.
I dont know if its because i have a namespace, admin/users or its because its the index action and not the show action.
any insight is welcome.
I've found the solution,
it seems the error was the update url it was wrong because of the namespace.
What i had to do, was to include url parameter like below
<td><%= best_in_place user, :name, url: "users/#{user.id}" %></td>
I am having problems with the following scenario:
My users do searches by keywords which produces a list. The user has 2 actions either add them to a favorites table or block them using check boxes.
The problem I have is that when users click "Add to Favorites" the form passes a list of hashes to my strong params method and I am not able to pass it correctly.
I think the problem is that the hash required by strong_params is inside another hash.
Also I have no idea on how to pass the same hash to the BlockController when user click "Block"
This is the error message:
param is missing or the value is empty: {:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}
My results.html.erb is
<table class="table table-striped table-bordered">
<tr>
<th class="center">Name</th>
<th class="center">Title</th>
<th class="center">Company</th>
<th class="center">Location</th>
<th class="center">Profile</th>
<th class="center">Select</th>
</tr>
<%= form_tag favorites_path do %>
<%= #results.length %>
<% #results.each do |key,value| %>
<tr>
<td><%= value['name'] %></td>
<td><%= value['title'] %></td>
<td><%= value['company'] %></td>
<td><%= value['location'] %></td>
<td><%= link_to 'Profile', value['profile'],:target => "_blank"%></td>
<td><%=check_box_tag 'favorite[]', {:name => value['name'],:title =>value['title'],:company => value['company'],:location => value['location'], :profile=> value['profile'], :notes =>""}%></td>
</tr>
<% end %>
<%= submit_tag "Add to Favorites", name: 'add', class: 'btn btn-primary' %>
<%= submit_tag "Block Profiles", name: 'block', class: 'btn btn-danger' %>
<% end %>
</table>
this is how my strong_params method looks:
def favorite_params
params[:profiles].each do |e|
params.require(e).permit(:name, :title, :company, :location, :profile, :notes)
end
end
Any ideas?
Update:
I am able to pass params as:
def favorite_params
params.permit(:commit,favorite:[])
end
create method:
def create
#favorite = Favorite.new(favorite_params)
#favorite.user_id = current_user.id
respond_to do |format|
if #favorite.save
format.html { redirect_to #favorite, notice: 'Favorite was successfully created.' }
format.json { render :show, status: :created, location: #favorite }
format.js { render :show, status: :created, location: #favorite }
else
format.html { render :new }
format.json { render json: #favorite.errors, status: :unprocessable_entity }
end
end
end
Reference to http://api.rubyonrails.org/classes/ActionController/Parameters.html
Don't use each, use permit or require directly
Try this:
params.permit(profiles: {favorites: [:name, :title, :company, :location, :profile, :notes]})
#or :
params.permit(profiles: [{favorites: [:name, :title, :company, :location, :profile, :notes]}])
#=>{:profiles=>{:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}}
or :
params.require(:profiles).permit( favorites: [:name, :title, :company, :location, :profile, :notes])
#=>{:favorites=>{:name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""}}
UPDATE
According to OP's modification of the view, the favorite_params should be:
params.require(:favorite)
Then in the create action use each to create every member of the array, becase check_box pass string as value, we have to eval the string into hash again.
favorite_params.each do |fp|
f=Favorite.new(eval(fp))
f.user_id = current_user.id
f.save
end
But use eval to transfer the params is not safe. I suggest you to modify your view to:
<%= form_tag favorites_path do %>
<%= #results.length %>
<% #results.each do |key,value| %>
<tr>
<td><%= value['name'] %></td>
<td><%= value['title'] %></td>
<td><%= value['company'] %></td>
<td><%= value['location'] %></td>
<td><%= link_to 'Profile', value['profile'],:target => "_blank"%></td>
<td><%= check_box_tag "favorites[#{value['name']}][checked]", 'checked',true %>
<%= hidden_field_tag "favorites[#{value['name']}][name]" , value['name'] %>
<%= hidden_field_tag "favorites[#{value['name']}][title]" , value['title'] %>
<%= hidden_field_tag "favorites[#{value['name']}][company]" , value['company'] %>
<%= hidden_field_tag "favorites[#{value['name']}][location]" , value['location'] %>
<%= hidden_field_tag "favorites[#{value['name']}][profile]" , value['profile'] %>
<%= hidden_field_tag "favorites[#{value['name']}][note]" , "" %>
</td>
</tr>
<% end %>
<%= submit_tag "Add to Favorites", name: 'add', class: 'btn btn-primary' %>
<%= submit_tag "Block Profiles", name: 'block', class: 'btn btn-danger' %>
<% end %>
From this view, you may have params like this:
{:favorites=>{
"Jon Doe" => {:checked => "checked", :name=>"Jon Doe", :title=>"Provider", :company=>"Acme", :location=>"Dubai", :profile=>"Group A", :notes=>""},
"Alberto" => {:name=>"Alberto", :title=>"DS", :company=>"Dufrain", :location=>"chester", :profile=>"", :notes=>""}
}
}
Then change your favorite_params to :
params.require(:favorites).select{|k,v| v[:checked]}.map{|k,v| v.except(:checked)}
Use select to get all checked members, and except the checked hash key that generated by check_box,so you could get an array of hashes like:
[{"name"=>"Jon Doe", "title"=>"Provider", "company"=>"Acme", "location"=>"Dubai", "profile"=>"Group A", "notes"=>""}]
Then you could use favorite_params safely without eval.
But on my point, your requiement is so similar as Mark V's question. So you can study using accepts_nested_attributes_for to simplify your code.
i am on the way home so have to use my phone to type a new answer. my spell may wrong.
as you see in your console. you should get the favorites array use require only.
params.require(:favorite)
then in your create action use each to create every member of the array.
favorite_params.each do |fp|
f=Favorite.new(fp)
f.user_id =
f.save
end
What I Want:
I need in a view a button or a link (it doesn't matter) to the create action of Reservation controller and to give it a parameter too.
And resolve the ForbiddenAttributesError that now gives me.
Here are my model and controller:
Reservation model
class Reservation < ActiveRecord::Base
belongs_to :user
belongs_to :dinner
end
Reservation controller
class ReservationsController < ApplicationController
load_and_authorize_resource
def show
#reservations = Reservation.joins(:user).where('dinner_id' => params[:dinner_id]).select("users.*,reservations.*")
#dinnerid = params[:dinner_id]
respond_to do |format|
format.html
format.json { render :json => #reservations }
end
end
def create
#reservation = Reservation.new(params[:reservation])
#reservation.user_id = current_user.id
respond_to do |format|
if #reservation.save
format.html { redirect_to #reservation, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
else
format.html { render :show }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def reservation_params
params.require(:reservation).permit(:dinner_id)
end
end
EDIT: After the suggestion of #Rahul Singh this is my actual code with relative error:
<p id="notice"><%= notice %></p>
<table>
<thead>
<tr>
<th>Id</th>
<th>User id</th>
<th>Dinner id</th>
<th>User email</th>
<th>User name</th>
</tr>
</thead>
<tbody>
<% #reservations.each do |reservation| %>
<tr>
<td><%= reservation.id %></td>
<td><%= reservation.user_id %></td>
<td><%= reservation.dinner_id %></td>
<td><%= reservation.user.email %></td>
<td><%= reservation.user.name %></td>
</tr>
<% end %>
</tbody>
</table>
<br/>TRY 00a <br/>
<%= form_for(Reservation.new) do |f| %>
<%= f.hidden_field( :dinner_id, :value => #dinnerid.to_s) %>
<%= f.submit "Join1" %>
<% end %>
<br/> !!!!!!!!!!ERROR : ActiveModel::ForbiddenAttributesError
<br/>TRY 00b <br/>
<%= link_to "Join1", reservations_path(dinner_id:#dinnerid.to_s), method: :post %>
<br/> !!!!!!!!!!ERROR : param is missing or the value is empty: reservation
I provide a sreenshot for the error :
Error of the form : https://www.dropbox.com/s/i2x1m520ptqdj56/createReservationForm.jpg
Error of the link_to : https://www.dropbox.com/s/8xjwee5oo7q6uhk/createReservationLink_to.jpg
This should work
<%= form_for(Reservation.new) do |f| %>
<%= f.hidden_field( :dinner_id, :value => #dinnerid.to_s) %>
<%= f.submit "Join1" %>
<% end %>
clicking on Join1 button will submit form to ReservationsController create action.
and with link try this
<%= link_to "Join1", reservations_path(dinner_id:#dinnerid.to_s), method: :post %>
for above to work,add following in your routes.rb
resources :reservations
Change this line -> #reservation = Reservation.new(params[:reservation])
To this -> #reservation = Reservation.new reservation_params
and try again ;).
I'm wondering if it wouldn't be better to have your reservation routes as a nested resource of dinners.
It seems reservations can't exist without a dinner, so I'd make that explicit like this:
# config/routes.rb
resources :dinners do
resources :reservations
end
Run rake routes to see how this would change the routes.
You'd now have the dinner id passed along:
# app/views/dinners/show.html.erb
<%= button_to 'Reserve this dinner', dinner_reservations_path(#dinner) %>
The button would route to the create action because a button's default HTTP method is POST.
# app/controllers/reservations_controller.rb
class ReservationsController < ApplicationController
before_action :set_dinner
def create
#dinner.reservations.create! user: current_user
# would render reservations/create.html.erb
end
private
def set_dinner
#dinner = Dinner.find(params[:id])
end
end
This doesn't fix your immediate problem of just getting that link to work. But I think you'd be a lot better served structuring your app more like the above going forward.
Full disclosure: the person who asked this question contacted me on twitter personally, so I took some liberties in answering this question with a more general design suggestion.
I'm not sure this is the "best" approach but I think its the easiest one.
You could do something with string interpolation:
a href="/reservations?dinner=#{dinner.id}" Join
then you could get the paramter with
params[:dinner]
I have 2 classes: Posts and Comments, where posts has_many :comments and comments belongs_to post.
Each of my posts has a show page with a list of comments and I would like to paginate the comments. With the current code I have, I'm showing a list of all the comments on all the pages. So, If i have 10 comments and I want to have 2 on each page, I get 5 pages with the original 10 comments on it. Could someone shed some light?
My Code:
Posts controller:
def show
#post = Post.find(params[:id])
#comments = #post.comments.page(params[:page]).per(3)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
"Show" views:
<%= paginate #comments %>
<% #post.comments.each_with_index do |comments, index| %>
<tr>
<td><%= index+1 %></td>
<td><%= comment.date %></td>
<td><%= comment.text %></td>
</tr>
<% end %>
</table>
You need to use the paginated object in the view, not get them fresh from the database:
<% #comments.each_with_index do |comments, index| %>
<tr>
<td><%= index+1 %></td>
<td><%= comment.date %></td>
<td><%= comment.text %></td>
</tr>
<% end %>
This gets them fresh, unpaginated:
#post.comments
I'm having trouble understanding the best way to make a advanced search form. I have had a good search on the internet, looking at some ways, but I can't get them to work, as most of the suggestions are outdated. I have asked a question already, but I think I was too specific and I wasn't able to fix my problem. I am wanting to search on different text boxes and drop down boxes with one search button.
EDIT2:
projects_controller:
def index
#projects = Project.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #projects }
end
end
def search
#project_search = Project.search(params[:search]).order(sort_column + ' ' + sort_direction).paginate(:per_page => 2, :page => params[:page])
end
# GET /projects/1
# GET /projects/1.json
def show
#project = Project.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #project }
end
end
# GET /projects/new
# GET /projects/new.json
def new
#project = Project.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #project }
end
end
# GET /projects/1/edit
def edit
#project = Project.find(params[:id])
end
# POST /projects
# POST /projects.json
def create
#project = Project.new(params[:project])
#project.client = params[:new_client] unless params[:new_client].blank?
#project.exception_pm = params[:new_exception_pm] unless params[:new_exception_pm].blank?
#project.project_owner = params[:new_project_owner] unless params[:new_project_owner].blank?
#project.role = params[:new_role] unless params[:new_role].blank?
#project.industry = params[:new_industry] unless params[:new_industry].blank?
#project.business_div = params[:new_business_div] unless params[:new_business_div].blank?
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.json { render json: #project, status: :created, location: #project }
else
format.html { render action: "new" }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
# PUT /projects/1
# PUT /projects/1.json
def update
#project = Project.find(params[:id])
respond_to do |format|
if #project.update_attributes(params[:project])
format.html { redirect_to #project, notice: 'Project was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
# DELETE /projects/1
# DELETE /projects/1.json
def destroy
#project = Project.find(params[:id])
#project.destroy
respond_to do |format|
format.html { redirect_to projects_url }
format.json { head :no_content }
end
end
private
helper_method :sort_column, :sort_direction
def sort_column
Project.column_names.include?(params[:sort]) ? params[:sort] : "project_name"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
end
Search View:
<h1>Search</h1>
<%= form_tag search_path, method: :get do %>
<%= hidden_field_tag :direction, params[:direction] %>
<%= hidden_field_tag :sort, params[:sort] %>
<%= text_field_tag :project_name, params[:project_name] %>
<%= text_field_tag :client, params[:client] %>
<%= submit_tag "Search", name: nil %>
<% end %>
<table class = "pretty">
<table border="1">
<tr>
<th><%= sortable "project_name", "Project name" %> </th>
<th><%= sortable "client", "Client" %></th>
<th>Exception pm</th>
<th>Project owner</th>
<th>Tech</th>
<th>Role</th>
<th>Industry</th>
<th>Financials</th>
<th>Business div</th>
<th>Status</th>
<th>Start date</th>
<th>End date</th>
<% if false %>
<th>Entry date</th>
<th>Edited date</th>
<th>Summary</th>
<th>Lessons learned</tStackh>
<th>Customer benifits</th>
<th>Keywords</th>
<!th></th>
<!th></th>
<!th></th>
<% end %>
</tr>
<% #project_search.each do |t| %>
<tr>
<td><%= t.project_name %></td>
<td><%= t.client %></td>
<td><%= t.exception_pm %></td>
<td><%= t.project_owner %></td>
<td><%= t.tech %></td>
<td><%= t.role %></td>
<td><%= t.industry %></td>
<td><%= t.financials %></td>
<td><%= t.business_div %></td>
<td><%= t.status %></td>
<td><%= t.start_date %></td>
<td><%= t.end_date %></td>
<% if false %>
<td><%= t.entry_date %></td>
<td><%= t.edited_date %></td>
<td><%= t.summary %></td>
<td><%= t.lessons_learned %></td>
<td><%= t.customer_benifits %></td>
<td><%= t.keywords %></td>
<% end %>
<!td><%#= link_to 'Show', project %></td>
<!td><%#= link_to 'Edit', edit_project_path(project) %></td>
<!td><%#= link_to 'Destroy', project, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
<%= will_paginate (#project_search) %>
<%= button_to "Search Again?", search_path, :method => "get" %>
<%# end %>
<%= button_to "Home", projects_path, :method => "get" %>
Project.rb
class Project < ActiveRecord::Base
attr_accessible :business_div, :client, :customer_benifits, :edited_date, :end_date, :entry_date, :exception_pm, :financials, :industry, :keywords, :lessons_learned, :project_name, :project_owner, :role, :start_date, :status, :summary, :tech
validates_presence_of :business_div, :client, :customer_benifits, :end_date, :exception_pm, :financials, :industry, :keywords, :lessons_learned, :project_name, :project_owner, :role, :start_date, :status, :summary, :tech
def self.search search_term
return scoped unless search_term.present?
where find(:all, :conditions => ['project_name OR client LIKE ?', "%#{search_term}%"])
end
end
Routes:
FinalApp::Application.routes.draw do
resources :projects
match "search" => "projects#search", :as => :search
root :to => 'projects#index'
end
As you can see, I'm still a fair bit away from having a finished application. I am trying to make a search form that will be able to search on the following fields: Project name, Client, ID, Industry, Role, Technology, Project Owner, Status, Start Date, End Date, and Keywords. The search form would have either text boxes or drop down menus depending on which field the user was searching for. I am wanting to chain each field and search on them all in one go. Before, I was only using project_name, and client as examples to make it easier for you to understand my code. Hopefully you can see now what I am trying to do.
You can create a new controller called search.
Your search form:
<%= form_tag search_index_path, method: :get do %>
<%= text_field_tag :project, params[:project] %>
<%= text_field_tag :client, params[:client] %>
<%= submit_tag "Search", name: nil %>
<% end %>
incude in your routes.rb:
get "search/index"
your search controller:
def index
#store all the projects that match the name searched
#projects = Project.where("name LIKE ? ", "%#{params[:project]}%")
#store all the clients that match the name searched
#clients = Client.where("name LIKE ? ", "%#{params[:client]}%")
end
Now you can play with #projects and #clients in the index view.
Just be careful, because these variables might became nil if there is no match for the search.
EDIT - I am assuming you have two models Project and Client - if you cannot create a new controller you can create the search action in your current controller.
def search
#store all the projects that match the name searched
#projects = Project.where("name LIKE ? ", "%#{params[:project]}%")
#store all the clients that match the name searched
#clients = Client.where("name LIKE ? ", "%#{params[:client]}%")
end
And than you can use the #projects and #clients in the search view.
If you are trying to display the results in somewhere else (for example index view), you can just move the above to the correct action.
def index
....
#store all the projects that match the name searched
#projects = Project.where("name LIKE ? ", "%#{params[:project]}%")
#store all the clients that match the name searched
#clients = Client.where("name LIKE ? ", "%#{params[:client]}%")
end
EDIT 2 - OK, you are trying to search by a combination of fields in the same model:
You and change your search method to add these two fields:
def self.search(search_project, search_client)
return scoped unless search_project.present? || search_client.present?
where(['project_name LIKE ? AND client LIKE ?', "%#{search_project}%", "%#{search_client}%"])
end
But please note the || will return scope if your search_project OR search_client are not present, you can change for AND (&&) if you prefer.
Also, the AND will return only if both match, I mean the combination of search... You can also change it to OR if you want.
Having the search form:
Your search form:
<%= form_tag search_index_path, method: :get do %>
<%= text_field_tag :project, params[:project] %>
<%= text_field_tag :client, params[:client] %>
<%= submit_tag "Search", name: nil %>
<% end %>
Then your controller must send the combination to the model:
#project_search = Project.search(params[:project], params[:client]).all
I think it will solve the problem...
I've been using MetaSearch in my application and found it quite convenient. If you've already considered it, what problems did you have?
There's also Ransack by the same author, it's a successor to MetaSearch.
A simple explanation can be found in this rails cast
Basically, we have to test if the params contain a specific field and create the filter. See the example below:
def find_products
products = Product.order(:name)
products = products.where("name like ?", "%#{keywords}%") if keywords.present?
products = products.where(category_id: category_id) if category_id.present?
products = products.where("price >= ?", min_price) if min_price.present?
products = products.where("price <= ?", max_price) if max_price.present?
products
end
An alternative is Ransack. Ransack enables the creation of both simple and advanced search forms for your Ruby on Rails application