why no implicit conversion of nil into Hash? - ruby-on-rails

after setup a search into a serializer!
Rails spits out
no implicit conversion of nil into Hash
So, please someone can point out whats wrong with this code?
class SearchController < ApplicationController
def results
results_query = PgSearch.multisearch(params[:q]).paginate(page: page, per_page: 20)
result = results_query.map(&:searchable).map do |result_item|
case result_item.class.name
when 'Post'
PostSerializer.new(result_item)
else
raise NotImplementedError
end
end
render json: {
items: result,
page: page,
pages: results_query.total_pages
}
end
def page
params[:page] || 1
end
def serialize(data, serializer)
ActiveModel::Serializer::CollectionSerializer.new(data, each_serializer: serializer)
end
end

Since your case statement isn't checking many values, you could always make it into a standard if/else statement:
if result_item && result.class.name == 'Post'
PostSerializer.new(result_item)
else
raise NotImplementedError
end

Well, on the screenshots you've provided we can see the log message specifies that the error is on line 5.
According to your code, line 5 is: case result_item.class.name
The error message is TypeError (no implicit conversion of nil into Hash).
You're trying to get the class then the name of result_item. So the problem is with result_item which is equal to nil.
In order the resolve your problem you might want to check the ouput of results_query.map(&:searchable).map.

Based on the screenshot you've provided, I've quickly checked the source code. The offending line seems to be this one: https://github.com/Casecommons/pg_search/blob/master/lib/pg_search/document.rb#L22. The only reason why this would raise the described TypeError is if PgSearch.multisearch_options is nil – which, as far as I understand the code, would only be possible if you accidentally overwrote it in a wrong way. So I'd suggest doublechecking your global setup for PgSearch.multisearch_options to make sure this is actually set.
The east way to check the setting is by using a debugger or putting something like puts PgSearch.multisearch_options or Rails.logger.info 'PgSearch.multisearch_options' into the controller directly above the call that's failing.

Related

Kaminari Pagination TypeError

I`m using kaminari in rails 7 to make the apgination of my API, but when i try to see a page different of the first page, im taking a type error, when i try access "http://localhost:3000/products?page=3":
TypeError (no implicit conversion of Symbol into Integer)
My paginated products index:
# GET /products
def index
page_number = params[:page].try(:[], :number)
per_page = params[:page].try(:[], :size)
#products = Product.all.page(page_number).per(per_page)
paginate json: #products
end
Anyone has a clue to how solve this?
EDIT:
I created a initializer named api_pagination.rb and put on him:
ApiPagination.configure do |config|
config.page_param do |params|
params[:page][:number] if params[:page].is_a?(ActionController::Parameters)
end
config.per_page_param do |params|
params[:page][:size] if params[:page].is_a?(ActionController::Parameters)
end
end
And now i can access "http://localhost:3000/products?page%5Bnumber%5D=2&page%5Bsize%5D=12" , but it doesn't look right to me, or this is the right way?
Maybe you need to set default values? Try with:
page_number = params[:page].try(:[], :number) || 1
per_page = params[:page].try(:[], :size) || 20
if that doesn't work, check what's coming in those number and size params or share more information of your issue, like the whole error stacktrace, even better the full request log.

Guard against invalid page number (0) for will_paginate?

The will_pagify gem will_paginate will throw an error if you send it the param page=0. Is there a better way than declaring page = nil (or 1) if param[:page] =~ /^[0]{,}$/? Hoping this is to support zero-index pages and I can disable this with a function parameter.
*There may be other invalid inputs I haven't tested. Strings go to nil.
Update:
Trying to avoid:
begin
model = Model.where(...).paginate(page: params[:page])
<additional code>
rescue
model = Model.where(...).paginate(page: '1')
<redo additional code again or use function***>
vs.
current_page = clean_page(params[:page])
model = Model.where(...).paginate(page: current_page)
You can leverage what WillPaginate has already done to handle all cases as follows:
def clean_page(page)
begin
WillPaginate::PageNumber(page)
rescue WillPaginate::InvalidPage
1
end
end
and that will handle all the same issues because you are leveraging their validation process and anything that fails defaults to page 1.
Working Example

rails 5 ForbiddenAttributesError on bulk operations

i try to bulk operation in my rails controller this is my script
def update_by_user
user_skill_selected = UserSkillSelected.create(params[:user_skill_selected][:users])
# check through array if all is valid
if user_skill_selected.all? {|item| item.valid?}
render json: {json_status: save_success}
else
render json: {json_status: save_failed}
end
end
and this is my user_skill_selected_params
def user_skill_selected_params
params.require(:user_skill_selected).permit(:user_id, :subskill_id, :skill_id, :users => [])
end
unfortunately i get an error in my log, the log said
"exception": "#<ActiveModel::ForbiddenAttributesError:ActiveModel::ForbiddenAttributesError>",
after that i try to bulk operations from rails console with using create method with the array value and its work
can anyone solve this... :(
sorry for the bad english
This can be confusing. Your code is passing in params[:user_skill_selected][:users] to the model create method, instead of your user_skill_selected_params strong parameters, which is why you're seeing that error.
Change this line:
user_skill_selected = UserSkillSelected.create(params[:user_skill_selected][:users])
To this:
user_skill_selected = UserSkillSelected.create(user_skill_selected_params)
And it should eliminate this error.

Few line of codes are geting escaping at active admin custom page page_action

While working with Active Admin-> Custom Page -> page_action, I am facing difficulty in following code block pointed in the code. I was trying to test code reachablity by exception. I don't understand why won't I get exception if I place exception in position 2 in the code?
page_action :add_event, method: :post do
blogit_posts=params["featured_post"]["blog_posts_attributes"].values.map { |s|
{
:blogit_post_id=>s["blogit_post_id"],
:id=> s["id"] ? s["id"] : s["i/nd"],
:priority=>s["priority"],
:_destroy=>s["_destroy"]
}
}
blogit_posts.each do |blog_hash|
#raise "unknown" <-- 1. if i put here, I get exception for it
if blog_hash[:id]
b=BlogPost.find_by_id(blog_hash[:id].to_i)
else if blog_hash[:blogit_post_id]
b=BlogPost.find_by_blogit_post_id(blog_hash[:blogit_post_id].to_i)
end
#raise "unknown" <-- 2. if i put here, I **DO NOT** get exception for it
if blog_hash[:_destroy] && blog_hash[:_destroy]=="1"
b.is_featured=false # <--- trying to fix this code block
else
b.is_featured=true
end
b.priority =blog_hash[:priority].to_i
b.save
end
end
redirect_to admin_featuredpost_path, notice: "Featurd post updated "
end
If you were trying to format the code appropriately, you would’ve immediately found the error:
if blog_hash[:id]
b=BlogPost.find_by_id(blog_hash[:id].to_i)
else
if blog_hash[:blogit_post_id]
b=BlogPost.find_by_blogit_post_id(blog_hash[:blogit_post_id].to_i)
end
???
That said, you have opened if, that is closed 15 lines below. One should either use elsif for spaghetti ifs or properly close nesting ifs.
You probably are having trouble with this block:
if blog_hash[:id]
b=BlogPost.find_by_id(blog_hash[:id].to_i)
else if blog_hash[:blogit_post_id]
b=BlogPost.find_by_blogit_post_id(blog_hash[:blogit_post_id].to_i)
end
I believe what you meant was to write this:
if blog_hash[:id]
b=BlogPost.find_by_id(blog_hash[:id].to_i)
elsif blog_hash[:blogit_post_id]
b=BlogPost.find_by_blogit_post_id(blog_hash[:blogit_post_id].to_i)
end
please notice the elsif

Specifying allowed values for a method parameter

Like in title - for example I have a method DrawMe(what) and I want to allow to run this method when what argument is equal to one of this values: {"house", "garden", "cat", "dog"} - and if not then this method should be stopped and an error should be printed. Any ideas?
class Draw
ALLOWED = %w[house garden cat dog]
def self.me(what)
raise ArgumentError, "Unknown drawable '#{what}'" unless ALLOWED.include?(what)
# Otherwise, carry on!
puts "I'm going to draw a #{what}!"
end
end
Draw.me('garden') #=> I'm going to draw a garden!
Draw.me('cat' ) #=> I'm going to draw a cat!
Draw.me('morals') #=> RuntimeError: Unknown drawable 'morals'
However, note that most of the time you should not be ensuring that developers passed the right type of value into your method. Your method will raise its own error if something explodes as a result of misuse; it's a waste of your time and the computer's time to attempt to check and catch errors like this.
Edit: If you need to use this frequently, you could monkeypatch it in everywhere:
class Object
def ensure_in( enumerable )
unless enumerable.include?( self )
raise ArgumentError, "#{self} must be one of #{enumerable}"
end
end
end
def me(what)
what.ensure_in( ALLOWED )
# Go ahead
end

Resources