Is it possible to use MetaSearch on checkboxes for strings? - ruby-on-rails-3

I have an index page of Users that I want to filter with a search form using MetaSearch. However the values I want to search when I checkbox is clicked are stored as strings. For example, here's a form I want to apply MetaSearch to:
<% form_for(current_user.profile) do |f| %>
<table id="careerCriteria">
<tr>
<td class="normal"><%= current_user.profile.hometown %></td>
<td><%= check_box_tag :hometown %></td>
</tr>
<tr>
<td class="normal"><%= current_user.profile.current_city %></td>
<td><%= check_box_tag :current_city %></td>
</tr>
<tr>
<td class="normal"><%= current_user.profile.past_city %></td>
<td><%= check_box_tag :past_city %></td>
</tr>
</table>
<% end %>
My User model:
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
end
I don't want to use a search button. I want the filter(s) to be applied when the checkbox (or checkboxes) are clicked. I'm new to programming so any help would be appreciated!

You'll need a little ajax & query to accomplish this.
Here's a good article to show you how to make the checkbox submit the form.
http://trevorturk.com/2010/08/24/easy-ajax-forms-with-rails-3-and-jquery/
What you'll want to do is create an action in the controller that handles your search. Here's an example of a search action...
def search
if params[:term].blank?
raise "You must provide search criteria."
end
params[:term] = "%#{params[:term]}%"
conditions = " Description LIKE :term"
#careers = Career.all(
:conditions => [conditions, params],
:offset => params[:offset],
:limit => params[:limit]
)
respond_with #careers
end
You'll also need to setup a route for this search for this action.
resources :careers do
get "search/:term/:offset/:limit.:format", :action => "search", :constraints => { :offset => /\d+/, :limit => /\d+/ }
end
Once you get the form submitting to this action you should be able to use jQuery to update the results.
Now keep in mind if you don't want to use Ajax & jQuery to load the results you can do so, you'll just take the remote action out of the form tag and it will refresh the whole page.

Related

How to use index action of controller of a model that belongs to another model?

I'm coding a rails application to handle scheduling for university classes. Currently, I'm trying to make an index page to show all of the sections in the database, but I'm getting this error:
No route matches {:action=>"index", :controller=>"sections"}
However, when I look at my routes, I can see a controller action pair for section and index.
bin/rails routes
Prefix Verb URI Pattern Controller#Action
home_index GET /home/index(.:format) home#index
course_sections GET /courses/:course_id/sections(.:format) sections#index
POST /courses/:course_id/sections(.:format) sections#create
new_course_section GET /courses/:course_id/sections/new(.:format) sections#new
edit_course_section GET /courses/:course_id/sections/:id/edit(.:format) sections#edit
course_section GET /courses/:course_id/sections/:id(.:format) sections#show
PATCH /courses/:course_id/sections/:id(.:format) sections#update
PUT /courses/:course_id/sections/:id(.:format) sections#update
DELETE /courses/:course_id/sections/:id(.:format) sections#destroy
courses GET /courses(.:format) courses#index
POST /courses(.:format) courses#create
new_course GET /courses/new(.:format) courses#new
edit_course GET /courses/:id/edit(.:format) courses#edit
course GET /courses/:id(.:format) courses#show
PATCH /courses/:id(.:format) courses#update
PUT /courses/:id(.:format) courses#update
DELETE /courses/:id(.:format) courses#destroy
students GET /students(.:format) students#index
POST /students(.:format) students#create
new_student GET /students/new(.:format) students#new
edit_student GET /students/:id/edit(.:format) students#edit
student GET /students/:id(.:format) students#show
PATCH /students/:id(.:format) students#update
PUT /students/:id(.:format) students#update
DELETE /students/:id(.:format) students#destroy
root GET / home#index
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
Why does it not route correctly?
My section controller looks like this:
class SectionsController < ApplicationController
def index
#courses = Course.all
end
def create
#course = Course.find(params[:course_id])
#section = #course.sections.create(section_params)
end
def update
#course = Course.find(params[:course_id])
#section = #course.sections.find(params[:id])
#section.update(section_params)
end
def destroy
#course = Course.find(params[:course_id])
#section = #course.sections.find(params[:id])
#section.destroy
end
private
def section_params
params.require(:section).permit(:section_letter, :section_professor, :section_meetings, :section_capacity)
end
end
My index.html.erb view in the sections folder looks like this:
<h2>Sections</h2>
<table>
<tr>
<th>Number</th>
<th>Section</th>
<th>Name</th>
<th>Credit Hours</th>
<th>Professor</th>
<th>Meetings</th>
<th>Capacity</th>
</tr>
<% #courses.each do |course| %>
<% course.sections.each do |section| %>
<tr>
<td><%= course.course_num %></td>
<td><%= section.section_letter %></td>
<td><%= course.course_name %></td>
<td><%= course.course_credits %></td>
<td><%= section.section_professor %></td>
<td><%= section.section_meetings %></td>
<td><%= section.section_capacity %></td>
</tr>
<% end %>
<% end %>
</table>
And my routes file looks like:
Rails.application.routes.draw do
get 'home/index'
resources :courses do
resources :sections
end
resources :students
root 'home#index'
end
Any help is appreciated!
Its because the sections controller is a nested resource under the courses resource. There is a sections#index but it takes a :course_id parameter.
In other words there is no /sections path that directly maps to sections#index
If its a one-off endpoint you can declare this route
get 'sections' => 'sections#index', as: :sections
And you'd then need to update the #index method in the SectionsController and just pull all Sections like
#sections = Section.all

Getting input from view to scope an index

So I am trying to add the ability to select a user in the view, and then return only the Lists that are associated with that user. I can do this for now hard coded in the controller.
def show
#some_lists = List.sort(:boolean => true, :user_id => 3)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #some_list }
end
end
But I want to be able to choose the user from the views
<% #some_lists.each do |list| %>
<tr>
<td><%= list.id_name %></td>
<td><%= list.day %></td>
<td><%= list.start_time %></td>
<td><%= list.end_time %></td>
</tr>
<% end %>
What is the best way to go about doing this, I also plan on adding the ability to sort by the list.start_time and list.end_time as well
You'll definitely want to do this with AJAX. For the specific thing you want to do (filtering/sorting a table) there's a javascript plugin I would recommend:
DataTables
(you'll want to check out the documentation on server-side processing)
There's even a really nice tutorial to using it with rails in RailsCast #340

Update don´t get the value of local when doing an update using i18n

I have tried to use i18n internationalization in my application.
It works very well when I do a Show (index), Create, and Edit. My problem is when I do an update.
When I press the update button I don´t get the :locale value back
Normaly I get these values back.
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
level: '5_3'
menu_item: '5'
menu_level: '5_3_1'
action: index
controller: communication_mails
locale: dk
The URL looks like:
localhost:3000/dk/communication_mails
When I press the Edit button I get these values back. (The “Button” is a link). Locale is still ok.
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
level: '5_3'
menu_item: '5'
menu_level: '5_3_2'
action: edit
controller: communication_mails
locale: dk
id: '2'
The URL now looks like:
localhost:3000/dk/communication_mails/2/edit
My problem is when I now press the “Update” button under the form field the redirection don´t get the value of locale back... It instead uses the ID.
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
level: '5_3'
menu_item: '5'
menu_level: '5_3_1'
action: index
controller: communication_mails
locale: '2'
The URL now looks like:
localhost:3000/2/communication_mails
My route looks something likes this:
scope "/:locale" do
resources :communication_mails
end
resources :communication_mails do
collection do
get 'communication_mails'
post 'communication_mails'
put 'communication_mails'
end
end
root :to => redirect("/dk/tests/")
match '/communication_mails/:id/edit(.:format)', :to => 'communication_mails#edit'
match '/communication_mails/:id/', :to => 'communication_mails#index'
match '/communication_mails', :to => 'communication_mails#index'
My Controller is made like this.
def edit
#communication_mail = CommunicationMail.find(params[:id])
#show_calendars = Calendar.where(:calendar_priority => '1')
#show_email_text = CommunicationMail.find_by_sql("SELECT calendars.id,
calendar_name, communication_mail_headline, communication_mail_text
FROM calendars LEFT OUTER JOIN communication_mails
ON communication_mails.communication_mail_calendar_id = calendars.id
WHERE communication_mails.communication_mail_priority = '1'")
end
def update
#communication_mail = CommunicationMail.update(params[:id], params[:communication_mail])
#show_calendars = Calendar.where(:calendar_priority => '1')
#show_email_text = CommunicationMail.find_by_sql("SELECT calendars.id,
calendar_name, communication_mail_headline, communication_mail_text
FROM calendars LEFT OUTER JOIN communication_mails
ON communication_mails.communication_mail_calendar_id = calendars.id
WHERE communication_mails.communication_mail_priority = '1'")
if #communication_mail
redirect_to communication_mails_path(:menu_item => '5', :level => '5_3', :menu_level => '5_3_1'),
:notice => 'Opdateringen af E-mail tekst lykkedes'
else
redirect_to communication_mails_path(:menu_item => '5', :level => '5_3', :menu_level => '5_3_1'),
:notice => 'Opdateringen af E-mail tekst lykkedes IKKE'
end
end
I have solved many questions by looking through these pages. But I can´t find an answer to this one.
I hope some one can help me out. Thanks in in advance.
UPDATE
My routes looks like this:
GET /:locale/communication_mails/communication_mails(.:format) communication_mails#communication_mails
POST /:locale/communication_mails/communication_mails(.:format) communication_mails#communication_mails
PUT /:locale/communication_mails/communication_mails(.:format) communication_mails#communication_mails
GET /:locale/communication_mails(.:format) communication_mails#index
POST /:locale/communication_mails(.:format) communication_mails#create
GET /:locale/communication_mails/new(.:format) communication_mails#new
GET /:locale/communication_mails/:id/edit(.:format) communication_mails#edit
GET /:locale/communication_mails/:id(.:format) communication_mails#show
PUT /:locale/communication_mails/:id(.:format) communication_mails#update
DELETE /:locale/communication_mails/:id(.:format) communication_mails#destroy
The form I use to send and update the data
<%= form_for(#communication_mail) do |f| %>
<table class="toggle_header2">
<tr>
<td class="nobr width50px font_size13 font_weight_bold color03 border_left">
<%= t('forms.calendar') %>
</td>
<td class="color03 border_right">
<%= collection_select(:communication_mail,
:communication_mail_calendar_id,
#show_calendars,
:id,
:calendar_name,
{:include_blank => true },
{:prompt => true})
%>
</td>
</tr>
<tr>
<td class="nobr width50px font_size13 font_weight_bold color03 border_left">
<%= t('forms.headline') %>
</td>
<td class="color03 border_right">
<%= f.text_field :communication_mail_headline, :class => 'width350px' %>
</td>
</tr>
<tr>
<td class="nobr align_top font_size13 font_weight_bold color03 border_left">
<%= t('forms.text') %>
</td>
<td class="color03 border_right">
<%= f.text_area :communication_mail_text, :class => 'width350px' %>
</td>
</tr>
<tr>
<td class="color03 border_left">
<%= f.hidden_field :communication_mail_priority, :value => '1' %>
</td>
<td class="color03 border_right">
<% if action_name == 'edit' || action_name == 'update' %>
<%= f.submit t('buttons.update') %>
<% else %>
<%= f.submit t('buttons.insert') %>
<% end %>
</td>
</tr>
</table>
<% end %>
If you pick your :locale value from params, you have incorrect approach in your routing.
Update: be sure you are passing :locale value to your routing helpers on update action.
This code will generate routes with scope only for index, show, new, create, edit, update, destroy actions.
scope "/:locale" do
resources :communication_mails
end
This code will add additional routes to :communication_mails, but without scope.
resources :communication_mails do
collection do
get 'communication_mails'
post 'communication_mails'
put 'communication_mails'
end
end
Solution is to combine. You have to define :scope for all of your :communication_mails actions.
scope "/:locale" do
resources :communication_mails do
collection do
get 'communication_mails'
post 'communication_mails'
put 'communication_mails'
end
end
end
Please read documentation about routing (it is basics): http://guides.rubyonrails.org/routing.html

Saving all nested form objects in one go

I'm trying to build two forms, nested. But all the resources I've found so far deal with how to save the main object, maybe add or remove nested objects, but not saving the entire list elsewhere with the values of the form. Is there a way to do this?
Here're the model I'm working with. I'm trying to create a pc configurator which will allow you to choose different components and quantities, and then you would add to the basket.
So I'm working with three models. Configuration, Configoption, Item.
-- Configuration model
has_many :configoptions
-- Configoption model
belongs_to :configuration
has_many :items
def range
a = []
b = self.quantity_rng.scan(/\w/)
b.each do |p|
a << p.to_i
end
return a
end
-- Item model
belongs_to :configoption
scope :sorted, order('items.position ASC')
The idea is that every configuration has a set of options, say 5. For each of these 5 options there could be a number of available items. For example option 1 is the processor, 2 could be RAM and so on.
-- Configuration controller
def list
#configurations = Configuration.find(:all)
end
def show
#configuration = Configuration.find(params[:id])
#options = #configuration.configoptions
end
-- configuration/show view
<table>
<tr>
<th>Elements</th>
<th>Quantity</th>
</tr>
<%= form_for(:configuration, :remote => true) do |p| %>
<% #options.each do |option| %>
<tr>
<%= form_for(:option, :remote => true) do |f| %>
<% if option.items.count > 1 %>
<th id="<%= option.name %>"> <%= f.select option.name, options_from_collection_for_select(option.items.sorted, 'id', 'name')%></th>
<% else%>
<th id="<%= option.name %>"> <%= f.label(option.items[0].name) %></th>
<% end %>
<% if option.quantity_rng == nil %>
<th id="<%= option.name + "_qty" %>"> <%= f.label(option.quantity) %></th>
<% else%>
<th id="<%= option.name %>"> <%= f.select option.name, option.range, :selected => option.quantity%></th>
<% end %>
<% end %>
<% end %>
</tr>
<% end %>
</table>
So far things are actually good, I can give different items to the options and the .range method let's me say quantity_rng in an option "1,2,3" and will make it into the array [1,2,3] passed for a drop-down if needed.
But now comes the crucial part, actually adding what I selected to the basket. How do I capture what the user has manipulated in the drop downs and store it (not as changes to the configoptions themselves, but as a new object elsewhere?)
BTW I'm using remote => true, because I intend to put some validation rules from jQuery later on, but one step at a time ;)
Thanks a lot!
May be i dint understand well your idea but i thing you need to use p.fields_for as nested options. Look at http://apidock.com/rails/v3.0.0/ActionView/Helpers/FormHelper/fields_for and dot forget to define
def address_attributes=(attributes)
# Process the attributes hash
end
in your model Configuration

how to query in view ruby on rails

i have this in the controller
#ads = Ad.all(:joins => 'LEFT JOIN states ON ads.state_id = states.id')
but i have problem to query field of states table.
any idea?
<% #ads.each do |ad| %>
<tr>
<td><%= ad.title %></td> <- title is ad field.no problem
<td><%= ad.name %></td> <- name is states field.problem at here
</tr>
<% end %>
I don't think this will work unless you have associations set up. Unless performance is a concern, you may just want to use the association without joins
ad.rb
class Ad < ActiveRecord::Base
belongs_to :state
end
state.rb
class State < ActiveRecord::Base
has_many :ads
end
controller
#ads = Ad.all
view
<% #ads.each do |ad| %>
<tr>
<td><%= ad.title %></td>
<td>
<%= ad.state.name %>
</td>
</tr>
<% end %>
I think you need to put this: ads.state_id = states.id like this: #{ads.state_id = states.id}
The #{ } will evaluate the ruby code inside. Otherwise what you have is just text inside a string.
I'm not quite sure what your issue is, though, so I'm not totally sure that will fix it.