I have a Rails 4 application. I have a search function with a select field. Now I'm getting this error:
NoMethodeError: undefined method 'map' for "5":String: select * from users inner join user_texts on users.id = user_id where text_id = ?
Here's view:
<% form_tag user_path do
<% select_tag :text_id, Option_from_collection_for_select(text.all, :id, :name, params[:text_id]), include_blank: true %>
<%= button_to '#', class: 'btn btn-default' do %>
<% t(:find) %>
<% end %>
Here's controller:
def index
if params[:text_id].present?
#users = User.search params[:text_id]
end
#users = User.all
end
Here's model:
def self.search(text_id)
find_by_sql("select * from users inner join user_texts on users.id = user_id where text_id = ?
", text_id)
end
When I do this, it works perfect:
select * from users inner join user_texts on users.id = user_id where text_id = 5
Change your method to this
def self.search(text_id)
User.joins(:user_texts).where("text_id = ?", text_id)
end
Two reasons why you should change
This is more rails-y way of doing it
find_by_sql doesn't work well with query placeholders
The above answer is perfectly fine and recommended, but sometimes you have to fetch from a raw sql query. And the error above is we need to use square brackets [ instead of round ( ones. Check out the API
So this should have worked.
def self.search(text_id)
find_by_sql ["select * from users inner join user_texts on users.id = user_id where text_id = ?
", text_id ]
end
Related
I have created a multi find search, where I need to filter records by date / category / title. Searching by a category and/or title works, however, when date is typed it doesn't change anything (the results is the same like there was no date typed). I have no idea what else I could do to fix it, I am just a beginner in Ruby. Any idea?
Model:
def self.multi_find(cat_id, search, date_search)
search_condition = "%" + search + "%"
#date_condition = date_search
# test if cat_id is not blank
if not cat_id.blank?
# assign the value of cat_id to a ‘scope’ named :cat
scope :cat, -> { where('category_id = ?', cat_id) }
# using the ‘scope’ cat find where a search string is like a title or an author’s name
self.cat.where("title LIKE ? or event_date = ?", search_condition, date_search.to_date)
else
# find where a search string is like a title or an author’s name
self.where("title LIKE ? or event_date = ?", search_condition, date_search.to_date)
end
end
Controller:
def multi_find
# call an Event class method, using two parameters; a category unique identifier and a search string (author or title)
events = Event.multi_find(params[:cat_id], params[:search_string], params[:event_date_search])
# use Kaminari pagination ...
#events = Kaminari.paginate_array(events.order :title).page(params[:page]).per(6)
# if no products have been found
if #events.empty?
# display a notice
flash.now[:alert] = "No events found - so displaying all events"
# then display all products
#events = Event.order(:title).page(params[:page]).per(6)
end
# use the index view
render :action => "index"
end
The console outputs the SQL Query
Event Load (0.0ms) SELECT "events".* FROM "events" WHERE (category_id = '1') AND (title LIKE '%%' or event_date = '2018-02-14') ORDER BY "events"."title" ASC
View file:
<%= form_tag my_path, :method=>'post', :multipart => true do %>
<%= select_tag ('cat_id'),
options_from_collection_for_select(#categories, :id, :cat_name, 0 ),
:prompt => "Select a Category" %>
<div class="datepicker">
<% #event_date_format %>
<%= text_field_tag :event_date_search %>
</div>
<!-- Key word:-->
<%= text_field_tag :search_string %>
<%= submit_tag 'Search' %>
<% end %>
It's because you have an or in your sql statement. However you should also clean up your code a bit.
def self.multi_find(cat_id, search, date_search)
result = self.all
result = result.where(category_id: cat_id) if cat.id.present?
result = result.where('title LIKE ?', "%#{search}%") if search.present?
result = result.where(event_date: date_search) if date_search.present?
result
end
There is a recommended solution and it seems to work. The issue is in my where clause and I'm not sure what's wrong.
For reference, here is the solution(s):
https://stackoverflow.com/a/7250426/4379077
https://stackoverflow.com/a/7250341/4379077
I am trying to scope users that are members of the current_user's family tree memberships(branches) user's within my Nodes controller. This would normally be done using this code (current_user.family_tree.memberships).
Note I have successfully set this up to autocomplete showing all users (User.all):
In my routes:
resources :nodes do
get :autocomplete_user_first_name, :on => :collection
end
In my Node controller I have the following code:
autocomplete :user, :first_name, :extra_data => [:last_name, :email],
display_value: :full_name
And in my view I have the following form:
<%= form_for node do |f| %>
<%= f.label :user_tags %>
<%= f.autocomplete_field :user_tags, autocomplete_user_first_name_nodes_path, 'data-auto-focus' => true, value: nil %>
<%= f.submit %>
<% end %>
When I attempt to add the recommended solution to my nodes controller:
def get_autocomplete_items(parameters)
items = super(parameters)
items = items.where(:user_id => current_user.family_tree.memberships)
end
I get this message:
NoMethodError - super: no superclass method "get_autocomplete_items" for #<NodesController:0x007fc516692278>:
So, I found this article https://stackoverflow.com/a/18717327/4379077 and changed it to
def get_autocomplete_items(parameters)
items = active_record_get_autocomplete_items(parameters)
items = items.where(:user_id => current_user.family_tree.memberships)
end
It works, but I get the following error
PG::UndefinedColumn: ERROR: column users.user_id does not exist, so I changed the where clause to this :id => current_user.family_tree.memberships and I get this result
User Load (0.9ms) SELECT users.id, users.first_name, "users"."last_name",
"users"."email"
FROM "users" WHERE (LOWER(users.first_name) ILIKE 'mi%')
AND "users"."id" IN (SELECT "memberships"."id" FROM "memberships"
WHERE "memberships"."family_tree_id" = $1)
ORDER BY LOWER(users.first_name) ASC LIMIT 10 [["family_tree_id", 1]]
The issue is that I believe I need to get a collection within the membership model comparing the attribute membership.user_id to user.id. What am I doing wrong in my where clause?
Are Membership objects the same thing as Users?
if not, you need to get the user_id off the membership record
This line would need to change
# use pluck to get an array of user_ids.
items = items.where(:id => current_user.family_tree.memberships.pluck(:user_id))
I'm trying to write a row for my index table that filters my objects regarding a specific value of a specific column. What I have until now is this:
pimps_controller.rb:
def index
#pimps = Pimp.search(params[:search])
end
pimp.rb:
def self.search( search)
if search
where('title LIKE ?', "%#{search}%")
else
scoped
end
end
A part of view:
<%= text_field_tag :search, params[:search] %>
That filters after the objects title only so I tried to alter it to make it functional for different search fields that can filter after different attributes. I want to pass a second parameter value if someone fires the search function to make sure it triggers for the right attributes. That's what I've tried:
pimps_controller.rb
#pimps = Pimp.search(params[:search_column],params[:search])
pimp.rb:
def self.search(search_column, search)
if search
col = "%#{search_column}"
s = "%#{search}%"
where(col 'LIKE ?', s)
else
scoped
end
end
The view:
<%= text_field_tag :search, params[:search], params[:search_column => title] %>
But it's not working. I get an error message for passing the both parameters in one search field I guess. How would you do it?
Here's a simple tutorial on how to do it:
https://we.riseup.net/rails/simple-search-tutorial
In the model, you will have to add the fields with or condition to the query.
def self.search(search)
search_condition = "%" + search + "%"
find(:all, :conditions => ['title LIKE ? OR description LIKE ?', search_condition, search_condition])
end
If you want to define the field to search in the params you can use string interpolation with simple quotes:
%q(text contains "#{search.query}")
You need 2 text fields, one for the column, one for the value:
# view
<%= text_field_tag :search_value, params[:search_value] %>
<%= text_field_tag :search_column, params[:search_column] %>
# controller
#pimps = Pimp.search(params[:search_column], params[:search_value])
# Pimp model
def self.search(search_column, search_value)
if search_value.present? && search_column.present?
column = self.column_names.include?(search_column.to_s) ? search_column : 'title'
value = "%#{search_value}%"
where("#{self.table_name}.#{column} LIKE ?", value)
else
scoped
end
end
The problem about this method is that if you don't type the exact name of the column, it will search the value in the column title. I think you should use a select_tag, listing all searchable columns of the model:
# view
<%= select_tag :search_column, options_for_select(Pimp.column_names.map { |col| [col, col] }, params[:search_column]) %>
This view code will display a select tag with the available columns of the Pimp model. You can easily limit the searchable columns by defining a class method on Pimp:
# Pimp model
def searchable_columns
self.column_names - ['id', 'created_at', 'updated_at']
end
# view
<%= select_tag :search_column, options_for_select(Pimp.searchable_columns.map { |col| [col, col] }, params[:search_column]) %>
I have a table without primary key with three columns - Player_ID, Season and Amount. When I want to update my current table I have this error message: ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'salaries.' in 'where clause': UPDATE salaries SET Season = 20192, Amount = 3232.0 WHERE salaries.`` IS NULL)
Update method in my controller:
def new
#salary = Salary.new
#players = Player.all
#title = "Add salary"
end
def create
#players = Player.all
#salary = Salary.new(params[:salary])
if #salary.save
flash[:success] = "Successfully added salary"
redirect_to salaries_path
else
#title = "Add salary"
render 'new'
end
end
def edit
#player_id = params[:player_id]
#season = params[:season]
#salary = Salary.find_by_Player_ID_and_Season(params[:player_id], params[:season])
#players = Player.all
#title = "Edit salary"
end
def update
#players = Player.all
#player_id = params[:player_id]
#season = params[:season]
#salary = Salary.find_by_Player_ID_and_Season(params[:player_id], params[:season])
if #salary.update_attributes(params[:salary])
flash[:success] = "Successfully edited salary"
redirect_to salaries_path
else
render 'edit'
end
end
_form.html.erb
<%= form_for(#salary, :url => salary_path(:player_id => #player_id, :season => #season)) do |f| %>
<%= f.collection_select :Player_ID, #players, :ID, :Name %>
<%= f.text_field :Season %>
<%= f.text_field :Amount %>
<%= f.submit "Add" %>
<% end %>
Active Record models have to have a primary key or rows can't be updated or delete.
There is a composite_primary_keys gem if you really don't want to add an ID column to your table (although adding that primary key is certainly the path of least resistance)
Your table has already primary key! It's the id attribute.
The params[:season] ... i think it's params[:salary][:season], right?
I think you should write in downcase season, player_id, amount. After that, if it still has problem, post new code here^^
I know the reason for your error, although the root cause isn't immediately clear to me. Your failing query is this:
ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'salaries.' in 'where clause': UPDATE salaries SET Season = 20192, Amount = 3232.0 WHERE salaries.`` IS NULL)
The important part is this:
WHERE salaries.`` IS NULL
It would make a certain amount of sense if it were WHERE salaries.foo IS NULL or WHERE salaries.bar IS NULL, but you just have empty space where a column name would normally be. So I guess MySQL (for some weird reason) is interpreting that to mean that you're talking about a column called salaries (i.e. salaries.salaries), which doesn't exist.
I don't even know why the WHERE clause is in there in the first place.
Does your create action work?
Update: the problem is almost certainly this line:
if #salary.update_attributes(params[:salary])
I believe what you want instead is:
if #salary.update_attributes(:amount => params[:amount])
See if that does anything.
I have recently uploaded my application to heroku and due to the postgresql, the case sensitivity does not work, I am wondering how will I fix this? My code is as followed:
relation = Game.gamsearch(params[:gamsearch])
relation = Game.consearch(params[:consearch]) if params[:consearch].present?
relation = Game.gensearch(params[:gensearch]) if params[:gensearch].present?
relation = Game.where("game_name LIKE ?", "#{params[:game_name]}%") if params[:game_name].present?
relation = Game.where("console = ?", params[:console]) if params[:console].present?
view code:
<%= form_tag games_path, :controller => 'games', :action => 'gamsearch', :method => 'get' do %>
<%= text_field_tag :gamsearch, params[:gamsearch] %>
<%= submit_tag t('.searchb'), :game_name => nil %>
<% end %>
This is the model code:
def self.gensearch(*args)
#search for games by their genre
return [] if args.blank?
cond_text, cond_values = [], []
args.each do |str|
next if str.blank?
cond_text << "( %s )" % str.split.map{|w| "genre LIKE ? "}.join(" OR ")
cond_values.concat(str.split.map{|w| "%#{w}%"})
end
all :conditions => [cond_text.join(" AND "), *cond_values]
end
relation = Game.where("game_name ILIKE ?", "#{params[:game_name]}%") if params[:game_name].present?
notice the ILIKE instead of LIKE
ILIKE is the way to go for PG, but if you have another database (sqlite) in development, that might not work. One way to get around this is to make both values uppercase and then compare the uppercased version of both.