rails 3.2 ice_cube and recurring_select - ruby-on-rails

I'm trying to save a recurring_select to a serialized attribute to handle recurring events on a rails app.
Using Jayson's post I manage to get the schedule saved but now I can't get the saved
attribute shown in index view or update the recurring_select in _form view
This is my model
class Todo < ActiveRecord::Base
attr_accessible :item, :completed, :schedule, :start_date
after_initialize :default_values
validates :item, presence: true
belongs_to :list
belongs_to :tasklib,
:foreign_key=>"item"
#recuring model
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :schedule
serialize :schedule, Hash
def schedule=(new_schedule)
write_attribute(:schedule,RecurringSelect.dirty_hash_to_rule(new_schedule).to_hash)
end
def converted_schedule
the_schedule = Schedule.new(self.start_date)
the_schedule.add_recurrence_rule(RecurringSelect.dirty_hash_to_rule(self.schedule))
the_schedule
end
end
This is my index view :
h1><%= #list.name %></h1>
<table class="table table-striped">
<thead>
<tr>
<th><%= model_class.human_attribute_name(:item) %></th>
<th><%= model_class.human_attribute_name(:start_date) %></th>
<th><%= model_class.human_attribute_name(:schedule) %></th>
<th><%=t '.actions', :default => t("helpers.actions") %></th>
</tr>
</thead>
<tbody>
<% #list.todos.each do |todo| %>
<tr>
<td><%= todo.item %></td>
<td><%= todo.start_date %></td>
<td><%= todo.schedule %></td>
<td>
<%= link_to t('.edit', :default => t("helpers.links.edit")),
edit_list_todo_path(#list, todo), :class => 'btn btn-mini' %>
<%= link_to t('.destroy', :default => t("helpers.links.destroy")),
list_todo_path(#list, todo),
:method => :delete,
:confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')),
:class => 'btn btn-mini btn-danger' %>
</td>
</tr>
<% end %>
</tbody>
</table>
and this is my _form view:
<%= simple_form_for [#list, if #todo.nil? then #list.todos.build else #todo end], :html => { :class => 'form-horizontal' } do |f| %>
<%-# f.input :item, input_html: {class: "span6", rows: 3} -%>
<%= f.collection_select :item, Tasklib.order(:name),:name,:name, include_blank: true %>
<%= f.label :start_date, "date" %>
<%= f.input :start_date %>
<%= f.label :schedule %>
<%= f.select_recurring :schedule, nil, :allow_blank => true %>
<div class="form-actions">
<%= f.submit 'Save', :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
lists_path, :class => 'btn' %>
</div>
<% end %>

OK I found it !
The model should be :
def schedule=(new_schedule)
if new_schedule == nil
new_schedule = IceCube::Schedule.new( self.start_date )
end
write_attribute(:schedule, RecurringSelect.dirty_hash_to_rule(new_schedule).to_hash)
end
def converted_schedule
if !self.read_attribute(:schedule).empty?
the_schedule = IceCube::Schedule.new( self.start_date )
the_rule = RecurringSelect.dirty_hash_to_rule( self.read_attribute(:schedule) )
if RecurringSelect.is_valid_rule?(the_rule)
the_schedule.add_recurrence_rule( the_rule)
end
the_schedule
end
end
and the form view should only set a new recurring select like:
<%= f.select_recurring :schedule, [ ["No recurring", "{}"] ], :allow_blank => true %>

Related

Rails - render a view in a view - pass params

In my app, I can call a view ('edit.html.erb') using:
<%= link_to( tag.content, [object, tag], method: :patch) %>
What would be the equivalent if I would want to render it within an other view ?
How would I pass it the params?
Edit
In effect I have a view of the parent, in which I want to list the children (editable). These I could edit separately too. Simple solution is that I, create a _partial which I render from the parent's view as well as from edit.html.erb.
I can call this edit.html.erb (or update) using the link:
<%= link_to( tag.content, [object, tag], method: :patch) %>
This works. Now question is how to render that partial (let's call it _update.html.erb) using render? Still need to pass the parent (i.e. object) and child (tag) params. How do I do that using <% render partial "tags/update" PARAMS %>?
Edit for full example
What I am trying to achieve (in short) - allow editing of tags (child) in annotate view (parent).
For an existing record of model/ object "Annotation", I want to add tags for an attached PDF. I do this in a page/view named "Annotate", that I open from the Annotation edit view (using 'link_to'). This "Annotate" page has 2 columns (see screenshot below):
left pane: 2 sections - 1 to quickly add the tag(s) and - 2 to edit existing tags (listed in a table)
right pane: the PDF
Tags and Annotation have polymorphic relationship (set up as per this question)
_form.html.erb for Annotation
<div class="row">
<div class="col-md-6">
<%= simple_form_for #annotation, html: { class: 'form-horizontal', multipart: true },
wrapper: :horizontal_form,
wrapper_mappings: {
check_boxes: :horizontal_radio_and_checkboxes,
radio_buttons: :horizontal_radio_and_checkboxes,
file: :horizontal_file_input,
boolean: :horizontal_boolean
} do |f| %>
<div class="btn-toolbar btn-group", role="toolbar">
<%= f.button :submit, 'Save', :class => "btn btn-xs btn-default" %> <%= link_to 'List' , annotations_path, :class => "btn btn-xs btn-default" %> <% unless #annotation.file.blank? %>
<%= link_to 'Annotate', annotate_path(#annotation), :class => "btn btn-xs btn-default" %>
<% end -%>
</div>
<h4>Annotation</h4>
<%= f.error_notification %>
<% if #annotation.file.blank? %>
<%= f.input :file, as: :file, input_html: { accept: ('application/pdf') } %>
<% else %>
<% end -%>
<%= f.input :name, placeholder: 'Enter name' %>
<%= f.input :description, placeholder: 'Description', :input_html => { :rows => 3 } %>
<%= f.association :documenttype, :collection => Documenttype.active.order(:name), prompt: 'Select document type' %>
<%= f.association :sender, label: 'Submitted by' , prompt: 'Select sender' %>
<%= f.association :receiver, label: 'Specific to', prompt: 'Select recipient' %>
<%= f.input :active, as: :boolean %>
<% end -%>
</div>
<% unless #annotation.file.blank? %>
<div class="col-md-6">
<%= content_tag :iframe, nil, src: pdf_annotation_path(#annotation), width: "100%", height: "770px", frameBorder: "0" %>
</div>
<% end %>
</div>
<% unless #annotation.new_record? %>
<div class="row">
<hr>
<div class="col-md-6">
<%= render #annotation.comments %>
</div>
<div class="col-md-6">
<%= render 'comments/form', :object => #annotation %>
</div>
</div>
<% end -%>
Annotate view annotate.html.erb
<div class="row">
<div class="col-lg-5">
<div class="btn-toolbar btn-group" role="toolbar">
<%= link_to 'Close', annotation_path(#annotation), :class => "btn btn-xs btn-default" %> <%= link_to 'List' , annotations_path, :class => "btn btn-xs btn-default" %>
</div>
<h4>Annotate document</h4>
<div data-spy="affix">
<%= render 'tags/form', :object => #annotation %>
<br>
<div class="panel panel-default" id="annotationResults">
<%= render 'tags/tag_list', :object => #annotation %>
</div>
</div>
</div>
<div class="col-lg-7" id="file">
<%= content_tag :iframe, nil, src: pdf_annotation_path(#annotation), width: "100%", height: "875px", frameBorder: "0" %>
</div>
</div>
tag list _tag_list.html.erb
<table id="tags" class="table table-hover" style="background-color: white; word-wrap: break-word; font-size: 0.9em;" >
<thead>
<tr>
<th>Tagged content</th>
<th>as</th>
<th>in</th>
<th></th>
</tr>
</thead>
<tbody>
<% object.tags.each do |tag| %>
<% unless tag.content.blank? %>
<tr data-tag-id='<%= tag.id %>', class='show-tag'>
<td style="word-wrap: break-word;"><%= link_to( tag.content, [object, tag], method: :patch) %>
<td><%= tag.tagtype.name %></td>
<td><%= tag.tagtype.typeoftag %></td>
<td><%= link_to '', [object, tag], method: :delete, data: { confirm: 'Please confirm!' }, :class => "glyphicon glyphicon-trash" %></td>
</tr>
<tr data-tag-id='<%= tag.id %>', class='edit-tag'>
<td colspan="4"><%= render partial: 'shared/tester' %><%#= render partial: 'tags/update', object: #tag.tagable, tag: #tag %></td>
</tr>
<% end -%>
<% end -%>
</tbody>
</table>
tag update form _update.html.erb
<%= simple_form_for [object, tag], html: { class: 'form-horizontal', multipart: true },
wrapper: :horizontal_form,
wrapper_mappings: {
check_boxes: :horizontal_radio_and_checkboxes,
radio_buttons: :horizontal_radio_and_checkboxes,
boolean: :horizontal_boolean
} do |f| %>
<div class="btn-toolbar btn-group" role="toolbar">
<%= f.button :submit, 'Save', :class => "btn btn-xs btn-default" %>
</div>
<%= f.error_notification %>
tag id = <%= #tag.id %>
<%= f.input :content, placeholder: 'Tagged content'%>
<%= f.association :tagtype, prompt: 'Select tag type', :collection => Tagtype.active.order(:name).where(:documenttype => #tag.tagable.documenttype_id) %>
<%= f.input :location, prompt: 'add as: x1, y1, x2, y2' %>
<% end -%>
Routes
Rails.application.routes.draw do
root 'dashboard#index'
devise_for :users
concern :tagable do
resources :tags, only: [:new, :index, :create, :edit, :update]
end
resources :users, :documenttypes, :tagtypes, :business_partners
resources :tags, only: [:show, :edit, :destroy, :index]
resources :documents do
resources :comments
resources :tags, concerns: :tagable
get "pdf", on: :member
end
resources :annotations do
resources :comments
resources :tags
get "pdf", on: :member
end
get "annotations/:id/annotate" => "annotations#annotate", as: 'annotate'
Tags controller
class TagsController < ApplicationController
def index
#tags = Tag.all.order(:tagable)
end
def show
tagable = detect_tagable
#tag = tagable.tags.find(params[:id])
end
def edit
tagable = detect_tagable
#tag = tagable.tags.find(params[:id])
#tag.update(tag_params)
end
def create
tagable = detect_tagable
tagable.tags.create(tag_params)
redirect_to tagable_path(tagable)
end
def update
tagable = detect_tagable
#tag = tagable.tags.find(params[:id])
render 'edit'
# #tag.save
#tag.update(tag_params)
end
def destroy
tagable = detect_tagable
#tag = tagable.tags.find(params[:id])
#tag.destroy
redirect_to tagable_path(tagable)
end
private
def tagable_path(tagable)
case tagable
when Document
document_path(tagable)
when Annotation
annotate_path(tagable)
else
fail 'Unknown tagable'
end
end
def detect_tagable
if params[:annotation_id]
Annotation.find(params[:annotation_id])
elsif params[:document_id]
Document.find(params[:document_id])
else
fail 'Tagable not found'
end
end
def tag_params
params.require(:tag).permit(:content, :location, :tagtype_id, annotation_attributes: { annotation_ids:[] }, document_attributes: { document_ids:[] })
end
end
This is what I have made - if there is a better way in Rails (which I can image) more then willing to learn.
The approach taken here should be to use nested forms, accepts_nested_attributes_for with allow_destroy: true and reject_if for the validations.
to destroy nested records, use accepts_nested_attributes_for :tags, allow_destroy: true and ensure that (besides :id) also :_destroy
is added to strongparams
to use validations for nested fields, use
accepts_nested_attributes_for :tags, allow_destroy: true,
reject_if: :something_to_check

SyntaxError at /setups/new: syntax error, unexpected tIDENTIFIER, expecting keyword_end

my controller:
class SetupsController < ApplicationController
def new
#setup = Setup.new
#todays_rate = #setup.todays_rates.build
end
def create
#setup = Setup.new(params[:setup])
if #setup.save
redirect_to setup_path(#setup)
else
render 'new'
end
end
end
My view code: setup/new.html.erb
<%= form_for #setup, :html => {:multipart => true} do |f| %>
<% if #setup.errors.any? %>
<ul>
<% #setup.errors.full_messages.each do |error| %>
<li><strong><%= error %></strong></li>
<% end %>
</ul>
<% end %>
<h4><%= f.label :effective_from, class:'required' %>
<%= f.text_field :effective_from %></h4>
<h4><%= f.label :effective_to, class:'required' %>
<%= f.text_field :effective_to %></h4>
<%= f.fields_for(:todays_rate) do |i| %> ##**combining two model with one view**
<h1>Interest Rate</h1>
<table cellpadding = "5px" cellspacing = "5px" width = "100%" class="table condensed-table"><tr>
<h4><th>Days From</th>
<th>Days To</th>
<th>Rate</th>
<th>Senior increment</th>
<th>Super Senior increment</th>
<th>Widow increment</th></h4>
</tr>
<h4><td><%= i.text_field :days_from, :class => 'input-mini' %></td></h4>
<h4> <td><%= i.text_field :days_to, :class => 'input-mini' %></td></h4>
<h4><td><%= i.text_field :rate, :class => 'input-mini' %></td></h4>
<h4> <td><%= i.text_field :senior_increment, :class => 'input-mini' %></td></h4>
<h4> <td><%= i.text_field :super_senior_increment,class:"input-mini" %></td></h4>
<h4><td><%= i.text_field :widow_incrtement,class: "input-mini" %></td></h4>
</table>
<% end %>
<fieldset class="form-actions"> <%= f.submit "Create Customer", class: "btn btn-primary" %></field>
setup.rb mmodel:
class Setup < ActiveRecord::Base
has_many :todays_rates
accepts_nested_attributes_for :todays_rates
attr_accessible :effective_from, :effective_to, :todays_rate
end
i'm combining two model in one view but i'm getting the above error. i don't know where i missed the keyword_end.can any one help me
I think your problem is that you haven't closed the form, ie you need a <% end %> at the end of your template.
The error sort of tells you that, though the tIDENTIFIER stuff can throw one off the scent a bit.

How to display validation errors when using nested forms?

First of all sorry about my English and about my knowledge of Rails, I am beginner who just started.
I have 2 models with relations:
CargoItems:
class CargoItem < ActiveRecord::Base
belongs_to :cargo
attr_accessible :cargo_id, :height, :length, :pieces, :weight, :width
validates :cargo, :height, :length, :width, :weight, :pieces, presence: true
validates :height, :length, :width, :pieces, numericality: { only_integer: true, greater_than_or_equal_to: 1}
validates :weight, numericality: { only_integer: true, greater_than_or_equal_to: 100}
end
Cargos:
class Cargo < ActiveRecord::Base
belongs_to :airport
belongs_to :user
belongs_to :cargo_state
belongs_to :cargo_price
belongs_to :cargo_description
has_many :cargo_items, :inverse_of => :cargo, :dependent => :destroy
attr_accessible :departure_date, :cargo_state_id, :airport_id, :cargo_price_id, :cargo_description_id, :cargo_items_attributes
accepts_nested_attributes_for :cargo_items, :allow_destroy => true, :reject_if => :all_blank
validates_associated :cargo_items
validates :departure_date, :cargo_state, :airport, :cargo_price, :cargo_description, presence: true
validates :departure_date, date: { after: Proc.new { Date.today - 1.day }, before: Proc.new { Time.now + 1.year } }, :on => :create
default_scope :order => 'departure_date DESC'
end
I use following GEMs: simple_forms, nested_forms. This is form to add new Cargo with multiple CargoItems (they have possibility to be added dynamically) belonging to Cargos:
<%= simple_nested_form_for #cargo, :wrapper => false do |f| %>
<%= f.association :airport, :label_method => :full_airport_name, :value_method => :id , :order => :iata_code %>
<%= f.input :departure_date , as: :date, start_year: Date.today.year,
end_year: Date.today.year + 16,
order: [:day, :month, :year] %>
<%= f.association :cargo_description, :label_method => :description, :value_method => :id, :order => :description %>
<%= f.association :cargo_price, :label_method => :price, :value_method => :id %>
<%= f.association :cargo_state, :label_method => :state, :value_method => :id %>
<hr>
<table>
<tr>
<th><%= :length %></th>
<th><%= :width %></th>
<th><%= :height %></th>
<th><%= :weight %></th>
<th><%= :pieces %></th>
</tr>
<%= f.simple_fields_for :cargo_items, #cargo_item do |cargo_items_fields| %>
<tr class="fields">
<td><%= cargo_items_fields.text_field :length %></td>
<td><%= cargo_items_fields.text_field :width %></td>
<td><%= cargo_items_fields.text_field :height %></td>
<td><%= cargo_items_fields.text_field :weight %></td>
<td><%= cargo_items_fields.text_field :pieces %></td>
<td><%= cargo_items_fields.link_to_remove "Remove this item", :confirm => 'Are you sure you want to remove this item?' %></td>
</tr>
<% end %>
</table>
<%= f.link_to_add "Add a item", :cargo_items %>
<div class="actions">
<%= f.button :submit %>
</div>
<% end %>
Cargo controller:
def new
#cargo = Cargo.new
#cargo_item = CargoItem.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #cargo }
end
end
def create
#cargo = Cargo.new(params[:cargo])
#cargo.user_id = current_user[:id]
respond_to do |format|
if #cargo.save
format.html { redirect_to #cargo, notice: 'Cargo was successfully created.' }
format.json { render json: #cargo, status: :created, location: #cargo }
else
format.html { render action: "new" }
format.json { render json: #cargo.errors, status: :unprocessable_entity }
end
end
end
My problem is, validation errors are not shown for CargoItems, model is actually validating. I am not able to save Cargos with CargoItems which does not fulfill validating rules. But in case validations are not met, Cargo is not saved and it just stayed on the same page without any notification that CargoItems fields are invalid. Cargos fields validation errors are shown properly.
Thanx a lot for helping me.
You need to add this errors notication before your form. Take a look at mine for example
<% if #author.errors.any? %>
<div class="alert alert-block">
<ul>
<% #author.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% if #book.errors.any? %>
<div class="alert alert-block">
<ul>
<% #book.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_for([#author, #book], html: { class: "well" }) do |f| %>
#labels and buttons...
<% end %>
I have an Author who has many Books, like so:
Author:
class Author < ActiveRecord::Base
attr_accessible :name
has_many :books, dependent: :destroy
accepts_nested_attributes_for :books, allow_destroy: true
validates :name, presence: true
validates :name, length: { minimum: 3 }
end
Book:
class Book < ActiveRecord::Base
attr_accessible :name, :year
belongs_to :author
validates :name, :year, presence: true
validates :year, numericality: { only_integer: true, less_than_or_equal_to: Time.now.year }
end
Simple Form also allows you to use label, hint, input_field, error and full_error helpers. for more detail documentation --> https://github.com/plataformatec/simple_form
Example code with error,
<%= simple_form_for #user do |f| %>
<%= f.label :username %>
<%= f.input_field :username %>
<%= f.hint 'No special characters, please!' %>
<%= f.error :username, id: 'user_name_error' %>
<%= f.full_error :token %>
<%= f.submit 'Save' %>
<% end %>

Virtual attribute in Ruby on Rails

I am a newbie in Rails. I am not understanding what I'm doing wrong here.
I have the following model order.rb, with a virtual attribute value:
class Order < ActiveRecord::Base
ACTIONS = %w(buy sell)
ORDER_TYPES = %w(LMT STP)
TIFS = %w(DAY GTC OPG IOC)
attr_accessible :action, :price, :quantity, :symbol, :tif, :order_type, :value
validates :action, :symbol, :tif, :order_type, presence: true
validates :price, numericality: { greater_than_or_equal_to: 0.0001 }
validates :quantity, numericality: { only_integer: true, greater_than: 0 }
validates :action, inclusion: ACTIONS
validates :order_type, inclusion: ORDER_TYPES
validates :tif, inclusion: TIFS
def value
price * quantity
end
def value= (val)
self.quantity = val / self.price
end
end
This model works fine in rails console, where I can set value and it calculates quantity.
The problem is when I try to visualize the form.
app/views/orders/new.html.erb renders the following _form.html.erb:
<%= form_for #order, html: { :class => 'form-inline' } do |f| %>
<% if #order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% #order.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<fieldset>
<legend><%= params[:action].capitalize %> Order</legend>
<table class="table">
<thead>
<tr>
<th><%= f.label :action %></th>
<th><%= f.label :symbol %></th>
<th><%= f.label :price %></th>
<th><%= f.label :value %></th>
<th><%= f.label :order_type %></th>
<th><%= f.label :tif, "TIF" %></th>
</tr>
</thead>
<tbody>
<tr>
<td><%= f.select :action, Order::ACTIONS, {}, class: 'input-small' %></td>
<td><%= f.text_field :symbol, class: 'input-small' %></td>
<td><%= f.text_field :price, class: 'input-small' %></td>
<td><%= f.text_field :value, class: 'input-small' %></td>
<td><%= f.select :order_type, Order::ORDER_TYPES, {}, class: 'input-small' %></td>
<td><%= f.select :tif, Order::TIFS, {}, class: 'input-small' %></td>
</tr>
</tbody>
</table>
<%= f.submit "Submit", class: "btn btn-primary" %>
<%= f.submit "Clear", class: "btn", type: "reset" %>
</fieldset>
<% end %>
I get an error when I open the page in the browser, raised on the line of _form.html.erb with the text field value:
NoMethodError in Orders#new
undefined method `*' for nil:NilClass
What am I doing wrong? I tried to follow http://railscasts.com/episodes/16-virtual-attributes
For the newly built order object price is nil. So you are getting this error.
Before calculating value make sure that you have price and quantity
def value
return unless price || quantity
price * quantity
end

Ruby on Rails: Show results on page, after search

I am trying to hide my search results until after the search has happened. At the moment when I click from the home page to the search page, the page shows the search boxes, but also shows all of the database in a table. I am wanting to just show the search options, and search button, then depending on the search, show the right table.
Here is my search view:
<h1>Search</h1>
<%= form_tag search_path, method: :get do %>
Client :
<%= select(#projects, :client, Project.all.map {|p| [p.client]}.uniq, :prompt => "-Any-", :selected => params[:client]) %></br>
Industry :
<%= select(#projects, :industry, Project.all.map {|p| [p.industry]}.uniq, :prompt => "-Any-", :selected => params[:industry]) %></br>
Role :
<%= select(#projects, :role, Project.all.map {|p| [p.role]}.uniq, :prompt => "-Any-", :selected => params[:role]) %></br>
Technologies :
<%= select(#projects, :tech, Project.all.map {|p| [p.tech]}.uniq, :prompt => "-Any-", :selected => params[:tech]) %></br>
Business Division :
<%= select(#projects, :business_div, Project.all.map {|p| [p.business_div]}.uniq, :prompt => "-Any-", :selected => params[:business_div]) %></br>
Project Owner :
<%= select(#projects, :project_owner, Project.all.map {|p| [p.project_owner]}.uniq, :prompt => "-Any-", :selected => params[:project_owner]) %></br>
Exception PM
<%= select(#projects, :exception_pm, Project.all.map {|p| [p.exception_pm]}.uniq, :prompt => "-Any-", :selected => params[:exception_pm]) %></br>
Start Date :
<%= text_field_tag("start_date") %></br>
End Date :
<%= text_field_tag("end_date") %></br>
Status :
<%= select(#projects, :status, Project.all.map {|p| [p.status]}.uniq, :prompt => "-Any-", :selected => params[:status]) %></br>
Keywords :
<%= text_field_tag :keywords, params[:keywords] %></br>
<%= submit_tag "Search", name: nil %>
<% end %>
<% if #search %>
<h3><%=#project_search.total_entries%> results</h3>
<% end %>
<% if #search %>
<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>
<%# end %>
<% #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><%= l t.start_date %></td>
<td><%= l 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>
Results per page: <%= select_tag :per_page, options_for_select([10,20,50], params[:per_page].to_i), :onchange => "if(this.value){window.location='?per_page='+this.value;}" %>
<br />
<%= hidden_field_tag :direction, params[:direction] %>
<%= hidden_field_tag :sort, params[:sort] %>
<%= hidden_field_tag :per_page, params[:per_page] %>
<%= hidden_field_tag :page, params[:page] %>
<%= will_paginate (#project_search) %>
<%= button_to "Search Again?", search_path, :method => "get" %>
<%# end %>
<%= button_to "Home", projects_path, :method => "get" %>
Here is the search action:
def search
#search = params[:client], params[:industry], params[:role], params[:tech], params[:business_div], params[:project_owner], params[:exception_pm], params[:status], params[:start_date], params[:end_date], params[:keywords]
#project_search = Project.search(#search)
#project = Project.new(params[:project])
respond_to do |format|
format.html # search.html.erb
format.json { render :json => #project }
end
end
and here is my model.
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_client, search_industry, search_role, search_tech, search_business_div, search_project_owner, search_exception_pm, search_status, search_start_date, search_end_date, search_keywords)
return scoped unless search_client.present? || search_industry.present? || search_role.present? || search_tech.present? || search_business_div.present? || search_project_owner.present? || search_exception_pm.present? || search_status.present? || search_start_date.present? || search_end_date.present? || search_keywords.present?
if search_start_date != ""
search_start_date = Date.parse(search_start_date).strftime("%Y-%m-%d")
end
if search_end_date != ""
search_end_date = Date.parse(search_end_date).strftime("%Y-%m-%d")
end
where(['client LIKE ? AND industry LIKE ? AND role LIKE ? AND tech LIKE ? AND business_div LIKE ? AND project_owner LIKE ? AND exception_pm LIKE ? AND status LIKE ? AND start_date LIKE ? AND end_date LIKE ? AND keywords LIKE ?', "%#{search_client}%", "%#{search_industry}%" , "%#{search_role}%" , "%#{search_tech}%" , "%#{search_business_div}%" , "%#{search_project_owner}%" , "%#{search_exception_pm}%" , "%#{search_status}%", "%#{search_start_date}%", "%#{search_end_date}%","%#{search_keywords}%"])
end
def self.paginated_for_index(projects_per_page, current_page)
paginate(:per_page => projects_per_page, :page => current_page)
end
end
Hopefully you can see what I have tried to do. I am getting the error wrong number of arguments (1 for 11) as I haven't split the params. But when I use *#search I get loads of errors.
My original code in the controller looked like this before I went about trying to hide the table:
#project_search = Project.search(params[:client], params[:industry], params[:role], params[:tech], params[:business_div], params[:project_owner], params[:exception_pm], params[:status], params[:start_date], params[:end_date], params[:keywords]).order(sort_column + ' ' + sort_direction).paginated_for_index(per_page, page)
You need to splat the #search params when passing it to .search to tell Ruby to expand your array of arguments to separate arguments to be passed to Project.search
#project_search = Project.search(*#search)
Information on using splat
Edit (to answer your follow-up question)
Testing with
<% if #search %>
isn't enough because it will always have a value that evaluates to true, even if its just [] or ["", "", "", "", "", "", "", "", "", "", ""]. One way to check this properly would be to create a new boolean instance variable that is true if all fields are blank in the search filters.
# put this after you set #search in your action
#search_performed = !#search.reject! { |c| c.blank? }.empty?
and now test #search_performed in your view with
<% if #search_performed %>
you are storing array in #search and u have to use * operator
#project_search = Project.search(*#search)

Resources