Rails 4 search bar - activerecord

I'm trying to create a search bar in my Rails 4 app. I'm my user db has 'name' and 'email' columns for the user's - I want users to be able to search for other users by name or id.
I'm currently getting this:
ActiveRecord::RecordNotFound in UsersController#index
Couldn't find all Users with 'id': (all, {:conditions=>["name LIKE ?", "%hi#example.com%"]}) (found 0 results, but was looking for 2)
Does anyone know what I'm doing wrong? I've looked at railscasts and a few forums etc but cant get past this point at the moment.
index.html.erb:
<% form_tag users_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
model/user.rb:
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
users_controller.rb:
def index
#users = User.search(params[:search])
end
routes.rb:
get 'search' => 'users#index'

Are you using Rails 4? find(:all, ...) is the old way of doing things. find only takes ids now. Use:
def self.search(search)
if search.present?
where('name LIKE ?', "%#{search}%")
else
where(true)
end
end
Also present? will test against both nil and blank. Keep in mind that LIKE can be really slow depending on your database.

Searching in rails
By default rails doesn't support full text searching .Activerecord finder always find a record using the primary key ie. id.
Hence , we need some other gems or applications like sunspot, elasticsearch etc..
i'll show you using Sunspot solr here ..
in the gem file of your application just add the following code...
.
gem 'sunspot_rails'
group :development do
gem 'sunspot_solr'
end
and in terminal use
bundle install
rails g sunspot_rails:install
this will add solr and creates config/sunspot.yml file
rake sunspot:solr:start
rake sunspot:reindex
edit the user.rb lile in models
app/model/user.rb
Class User < ActiveRecord::Base
searchable do
text :name, :email
end
end
in app/controller/users_controller.rb
and then add in index function
def index
#search = User.search do
fulltext params[:search]
end
#users = search.results
end
Make a form to take a user input
<%= label_tag(:search, "Search for:") %>
<%= text_field_tag(:search) %>
<%= submit_tag("Search") %>
<% end %>

Related

wrong number of arguments (3 for 2) in semantic_form_for tag

project details
ruby 2.4.1p111 and rails 4.2.8
Below is the code from my index page.
<%= semantic_form_for #threshold_configuration, :url => dm_threshold_configuration_path do |f| %>
//my code goes here//
<% end %>
in my index action i have the instance variable set.
def index
super
#threshold_configuration = ThresholdValues.first
end
when i load the page getting below error.
wrong number of arguments (3 for 2)
If i replace the semantic_form_for as below my page is loading.
<%= semantic_form_for :threshold_configuration, :url => dm_threshold_configuration_path do |f| %>
//my code goes here//
<% end %>
i'm not getting what exactly happening in the #threshold_configuration and :threshold_configuration. syntax which im using is fine according the formstatic gem manual.
Thnx in advance
Ajith

rails 3 multiple language for any user

I want my app has multiple languages. To do this, I read railscasts #138
But there, the writer put a language column to User model and thus users can see pages only in their language as I understand right. But I want my website can be seen in any language by any user just like usual.
How can this be done?
I have solved. I added to controllers/application_controller.rb this:
before_filter :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
private
def default_url_options(options={})
logger.debug "default_url_options is passed options: #{options.inspect}\n"
{ :locale => I18n.locale }
end
Then I added this to views/layouts/_header.html.erb:
<li><% if I18n.locale == I18n.default_locale %>
<%= link_to "Türkçe", :locale=>'tr'%>
<% else %>
<%= link_to "English", :locale=>'en'%>
<%end%></li>
Then to config/routes.rb this:
scope "(:locale)", :locale => /en|tr/ do # at the beginning
match '/home' , to: 'static_pages#home'
match '/help' , to: 'static_pages#help'
match '/about' , to: 'static_pages#about'
.....
end
Thats it!
You might want to take a look at this great Rails guide.
in addition to #Pierre-Louis answer, you can look at globalize3 gem

How to upload a file temporarily in Rails 3?

I'm creating CSV-upload functionality for a site of mine.
I'm looking to upload a file, parse it, and then dispose of it.
I know I can upload and save a file using Paperclip, but that seems a bit like overkill.
All I need to do is parse the uploaded file and never save it.
How would I go about doing this in Rails 3?
Note: I'd prefer to do the uploading manually without using an external gem so I can learn how to process works, but any suggestions are welcome.
Thanks!
Use the file_field helper in your form, then in your controller you can use File.Write and File.read to save the file.
E.g. View
<%= form_for #ticket do |f| %>
<%= f.file_field :uploaded_file %>
<% end %>
Controller
def upload
uploaded = params[:ticket][:uploaded_file]
File.open(<insert_filename_here>, 'w') do |file|
file.write(uploaded.read)
end
end
Edit: Just saw #klochner's comment, that link says pretty much what I have said so follow that: RubyOnRails Guides: Uploading Files.
Paste this in your model
def parse_file
File.open(uploaded/file/path, 'w') do |f| # Feed path that user gives in some way
## Parse here
end
end
this in view
<%=form_for #page, :multipart => true do |f|%>
<ul><li><%= f.label :file%></li>
<li><%= f.file_field :uploaded_file%></li></ul>
<%end%>
Let me know if this works. If it fails figure out a way to feed path of uploaded_file in parse_file method (the definite way which will work is storing file location in db and picking up from there, but it is not the right way to do this thing). Otherwise, I guess it should work.
Complete Example
Take, for example, uploading an import file containing contacts. You don't need to store this import file, just process it and discard it.
Routes
routes.rb
resources :contacts do
collection do
get 'import/new', to: :new_import # import_new_contacts_path
post :import, on: :collection # import_contacts_path
end
end
Form
views/contacts/new_import.html.erb
<%= form_for #contacts, url: import_contacts_path, html: { multipart: true } do |f| %>
<%= f.file_field :import_file %>
<% end %>
Controller
controllers/contacts_controller.rb
def new_import
end
def import
begin
Contact.import( params[:contacts][:import_file] )
flash[:success] = "<strong>Contacts Imported!</strong>"
redirect_to contacts_path
rescue => exception
flash[:error] = "There was a problem importing that contacts file.<br>
<strong>#{exception.message}</strong><br>"
redirect_to import_new_contacts_path
end
end
Contact Model
models/contact.rb
def import import_file
File.foreach( import_file.path ).with_index do |line, index|
# Process each line.
# For any errors just raise an error with a message like this:
# raise "There is a duplicate in row #{index + 1}."
# And your controller will redirect the user and show a flash message.
end
end

Sorting and manipulating a hash in Ruby

In my rails 3.1 project I have a Book model that has a ID, NAME, and BOOK_ORDER. I am using the ranked-model gem, which for its sorting process creates large numbers in the sorting(:book_order) column. Im looking for some help to create a method to sort all of the Books by the :book_order column, then simplify the :book_order numbers.
So, I have this:
controller
#books = Books.all
view
<% #books.each do |book| %>
<%= book.book_order %>
<% end %>
# book1.book_order => 1231654
# book2.book_order => 9255654
# book3.book_order => 1654
But want this:
view
<% #books.each do |book| %>
<%= book.clean_book_order %>
<% end %>
# book1.clean_book_order => 2
# book2.clean_book_order => 3
# book3.clean_book_order => 1
Additionally, i don’t want to change the database entry, just use its current values to make simpler ones.
Thanks!
UPDATE:
Thanks to nash’s response I was able to find a solution:
In my Book Model I added the clean_book_order method:
class Book < ActiveRecord::Base
include RankedModel
ranks :book_order
def clean_book_order
self.class.where("book_order < ?", book_order).count + 1
end
end
<% #books.each do |book| %>
<%= book.book_order_position %>
<% end %>
EDIT:
Oh, I see. https://github.com/harvesthq/ranked-model/issues/10

Rails: How to receive non-model form input, convert it to a model attribute, and then save that model

Background:
I have a form_for mapped to a model called List.
List has attributes: name, id, receiver_id, assigner_id.
I want the user( or list assigner) to be able to choose a list receiver.
I want the assigner to input an e-mail, rather than the receiver's id.
Problem:
I am not sure how to use a form to receive an e-mail address, run a "User.find_by_email(xx).id" query using that e-mail address, and then assign the returned id to the List's receiver_id attribute.
Current Code:
lists_conroller.rb
class ListsController < ApplicationController
before_filter :current_user
def new
#list = List.new
end
def create
#list = List.new(params[:list])
#list.assigner = #current_user
##list.receiver = User.find_by_id(:receiver_id)
#list.save
redirect_to #list
end
def show
#list = List.find(params[:id])
end
def update
#list = List.find(params[:id])
end
end
lists\new.html.erb
<%= form_for #list do |f| %>
<%= f.label :name, 'Name'%>
<%= f.text_field :name %>
<%= f.label :receiver_id, 'Receiver ID'%>
**I want this to be the e-mail input, rather than the integer id.**
<%= f.text_field :receiver_id %><br />
<%= f.submit :submit %>
<% end %>
User creates new list, with him as the assigner. In that creation process there must be a receiver too. Did I get this right?
I think the receiver should be selected from a list of possible receivers (maybe a select box? this will depend on the number of possible receivers though, wouldn't want to list 1000+ users in there - if there are many users you could do an ajax search when the user types a few letters)
The assigner then selects a user (with the corresponding id as the value) and everything should be ok.
The answer to my question is "Virtual Attributes..."

Resources