Link_to create with parameter before - ForbiddenAttributesError now - ruby-on-rails

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]

Related

Best in place gem not updating values - rails 4

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>

Rails 4 uninitialized constant Admin::Category

I have generated Admin namespaced Controllers for all my default models as follows:
rails g scaffold_controller admin/categories name:string slug:string description:string icon_xlarge:string icon_large:string icon_medium:string icon_small:string status:integer
This generated the following files:
Harshas-MacBook-Pro:nomad harshamv$ rails g scaffold_controller admin/categories name:string slug:string description:string icon_xlarge:string icon_large:string icon_medium:string icon_small:string status:integer
Plural version of the model detected, using singularized version. Override with --force-plural.
create app/controllers/admin/categories_controller.rb
invoke erb
create app/views/admin/categories
create app/views/admin/categories/index.html.erb
create app/views/admin/categories/edit.html.erb
create app/views/admin/categories/show.html.erb
create app/views/admin/categories/new.html.erb
create app/views/admin/categories/_form.html.erb
invoke test_unit
create test/controllers/admin/categories_controller_test.rb
app/model/category.rb
class Category < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
has_and_belongs_to_many :venues
end
app/controller/admin/categories_controller.rb
class Admin::CategoriesController < ApplicationController
before_action :set_admin_category, only: [:show, :edit, :update, :destroy]
# GET /admin/categories
def index
#admin_categories = Admin::Category.all
end
# GET /admin/categories/1
def show
end
# GET /admin/categories/new
def new
#admin_category = Admin::Category.new
end
# GET /admin/categories/1/edit
def edit
end
# POST /admin/categories
def create
#admin_category = Admin::Category.new(admin_category_params)
if #admin_category.save
redirect_to #admin_category, notice: 'Category was successfully created.'
else
render :new
end
end
# PATCH/PUT /admin/categories/1
def update
if #admin_category.update(admin_category_params)
redirect_to #admin_category, notice: 'Category was successfully updated.'
else
render :edit
end
end
# DELETE /admin/categories/1
def destroy
#admin_category.destroy
redirect_to admin_categories_url, notice: 'Category was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_admin_category
#admin_category = Admin::Category.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def admin_category_params
params.require(:admin_category).permit(:name, :slug, :description, :icon_xlarge, :icon_large, :icon_medium, :icon_small, :status)
end
end
app/view/admin/categories/index.html.erb
<h1>Listing admin_categories</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Slug</th>
<th>Description</th>
<th>Icon xlarge</th>
<th>Icon large</th>
<th>Icon medium</th>
<th>Icon small</th>
<th>Status</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #admin_categories.each do |admin_category| %>
<tr>
<td><%= admin_category.name %></td>
<td><%= admin_category.slug %></td>
<td><%= admin_category.description %></td>
<td><%= admin_category.icon_xlarge %></td>
<td><%= admin_category.icon_large %></td>
<td><%= admin_category.icon_medium %></td>
<td><%= admin_category.icon_small %></td>
<td><%= admin_category.status %></td>
<td><%= link_to 'Show', admin_category %></td>
<td><%= link_to 'Edit', edit_admin_category_path(admin_category) %></td>
<td><%= link_to 'Destroy', admin_category, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Category', new_admin_category_path %>
My Attempts
I edited the Controller as below
# GET /admin/categories
def index
#admin_categories = Category.all
end
# GET /admin/categories/1
def show
end
# GET /admin/categories/new
def new
#admin_category = Category.new
end
# GET /admin/categories/1/edit
def edit
end
# POST /admin/categories
def create
#admin_category = Category.new(admin_category_params)
if #admin_category.save
redirect_to #admin_category, notice: 'Category was successfully created.'
else
render :new
end
end
When I go to localhost/admin/categories and click "NEW category", I get the following error now:
My routes file:
Rails.application.routes.draw do
# Admin Routing
namespace :admin do
resources :categories, :cities, :countries, :lists, :oauths, :regions, :tags, :users, :user_groups, :venues, :venue_photos, :venue_reviews
end
end
You have resources :categories defined under the namespace :admin in your routes.rb,so this line in your views/admins/categories/_form.html.erb
<%= form_for(#admin_category) do |f| %>
should be
<%= form_for([:admin, #admin_category]) do |f| %>
For more info,refer this API
Update
The second error is because of this line
params.require(:admin_category).permit(:name, :slug, :description, :icon_xlarge, :icon_large, :icon_medium, :icon_small, :status)
It should be
params.require(:category).permit(:name, :slug, :description, :icon_xlarge, :icon_large, :icon_medium, :icon_small, :status)
To access models outside of the namespace you need to call ::Category.new instead of Admin::Category.new
As your error indicates, this is an issue with how you are calling your form. Your form needs to reference the admin namespace, like this:
<%= form_for [:admin, #category] do |f| %>
However, there are a number of things different about the way the scaffold built your docs from how I would recommend.
I would also suggest simplifying the code in the scaffolded controller to reference simple #category and #categories, rather than #admin_category and #admin_categories.
Also, the model should not be in the admin namespace, so Admin::Category.new should be Category.new. The rest of the model calls should be adjusted accordingly as well.

Got this error: param is missing or the value is empty: series

I am making a simple app where a user can create a Series and then an episode to the series, and then multiple links to each episode. I tried using the gem Cocoon but I wasn't able to get it to show up on the view.
I thought I had set everything right, but I hope someone can help me find what I am doing wrong or missing, thanks!
I am getting this error:
param is missing or the value is empty: series
And in the console:
Processing by SeriesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"KAF06O/2C3EBRwos7UnJGSzWF2SGVVB7YdrNnuWt0M=", "commit"=>"Update Series", "id"=>"2"}
Series Load (0.2ms) SELECT "series".* FROM "series" WHERE "series"."id" = ? LIMIT 1 [["id", "2"]]
Completed 400 Bad Request in 39ms
ActionController::ParameterMissing (param is missing or the value is empty: series):
app/controllers/series_controller.rb:64:in `series_params'
app/controllers/series_controller.rb:35:in `block in update'
app/controllers/series_controller.rb:34:in `update'
These are what my models look like:
# app/models/series.rb
class Series < ActiveRecord::Base
has_many :episodes
accepts_nested_attributes_for :episodes
end
# app/models/episode.rb
class Episode < ActiveRecord::Base
belongs_to :series
has_many :links
accepts_nested_attributes_for :links
end
# app/models/link.rb
class Link < ActiveRecord::Base
belongs_to :episode
end
My controller:
class SeriesController < ApplicationController
before_action :set_series, only: [:show, :edit, :update, :destroy, :links]
def new
#series = Series.new
#series.episodes.build
end
def update
respond_to do |format|
if #series.update(series_params)
format.html { redirect_to #series, notice: 'Series was successfully updated.' }
format.json { render :show, status: :ok, location: #series }
else
format.html { render :edit }
format.json { render json: #series.errors, status: :unprocessable_entity }
end
end
end
# ... ignoring content that hasn't changed from scaffold
def links
#episodes = #series.episodes
end
private
def series_params
params.require(:series).permit(:name,
episodes_attributes: [:id, :title,
links_attributes: [:id, :url]
])
end
end
The views files:
<!-- app/views/series/links.html.erb -->
<h1><%= #series.name %></h1>
<%= form_for(#series) do |f| %>
<table>
<thead>
<tr>
<td>Title</td>
<td>Season</td>
<td>Episode</td>
</tr>
</thead>
<tbody>
<% #episodes.each do |episode| %>
<tr>
<td><%= episode.title %></td>
<td><%= episode.season %></td>
<td><%= episode.episode %></td>
<td>
<%= f.fields_for :episodes, episode.build do |e| %>
<%= e.fields_for :links, episode.link.build do |a| %>
<%= a.text_area :url %>
<% end %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And the routes file:
MyApp::Application.routes.draw do
resources :series do
member do
get 'links'
end
end
end
I think series parameter is not passing from your view
Parameters: {"utf8"=>"✓", "authenticity_token"=>"KAF06O/2C3EBRwos7UnJGSzWF2SGVVB7YdrNnuWt0M=", "commit"=>"Update Series", "id"=>"2"}
in your action you are using series_params method in that you are using like params.require(:series).permit .
so it's throwing param is missing or the value is empty: series
please check in you view file you passing the view or not
You need to build your links too:
#app/controllers/series_controller.rb
def new
#series = Series.new
#series.episodes.build.links.build #-> creates one link object you can populate
end
Then you need to change your form to use the built link objects:
<%= f.fields_for :episodes do |e| %>
<%= e.fields_for :links do |a| %>
<%= a.text_area :url %>
<% end %>
<% end %>
This should get the new & create actions working. However, you posted the log for the update action -- are you having issues with create or update?

Rails and SQLITE: Images are not being displayed

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!!!

Ruby on Rails: Advanced search

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

Resources