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.
Related
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.
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.
I am building a daily deal Rails app
I am displaying to the user only the deals of the country i associate him with thanks to geocoder gem.
I wonder what would happen if geocoder fails (for any reason) to retrieve the country and sends an empty array, as i think it does when it fails to send ip( see https://github.com/alexreisner/geocoder#error-handling)
class StaticPagesController < ApplicationController
def home
#deals = deal_in_user_country.featured_on_hp
respond_to do |format|
format.html # home.html.erb
end
end
# create a scope to filter the deals that meet the user's country
def deal_in_user_country
Deal.where(country: set_location_by_ip_lookup.country || 'United States') # if geocoder gets pb then default = US version
end
end
end
As you see, I tried to use || and puts 'United States' but I don't think it will work. i think that if geocoder sends empty array , set_location_by_ip_lookup=[] and then set_location_by_ip_lookup.country will generate an error, am I right ?
How should i avoid bugs when geocoder sends an empty array ?
For info if it helps, here is how I set country in concerns/CountrySetter
module CountrySetter
extend ActiveSupport::Concern
included do
before_filter :set_location_by_ip_lookup
end
def set_location_by_ip_lookup
if Rails.env.development? or Rails.env.test?
Geocoder.search(request.remote_ip).first
else #in production
request.location
end
end
end
Your code should be fine, if geocoder allways returns at least an empty array (except I would not name this mehtod set_ because it's not setting anything)
Try out on irb
{a: [:d].first || :b}
=> {:a=>:d}
{a: [].first || :b}
=> {:a=>:b}
However i would put this in paranethesis to make it clear
Deal.where(country: (set_location_by_ip_lookup.country || 'United States'))
Gecodoer.search shouldn't be throwing exceptions, otherwise it would be named Geocoder.search! according to an unwritten ruby convention. I would double check this by plugin out the internet connection and see what happens
I am running the Kaminari gem for my pagination.
Controller
def dashboard
#projects = Project.find_by_user_id(current_user)
if #projects.size > 10
#projects.page(params[:page]).per(10)
end
end
Dashboard view
= paginate #projects, :theme => 'twitter-bootstrap-3', :remote => true
In my case, the #projects is sometimes only 1 record or even zero records. When it is nil, I get an error on the params[:page] being nil.
So this works
def dashboard
#projects = Project.page(params[:page]).per(10)
end
This gets error undefined method 'page' for #<Project:0x007f8cac5f14b0>
def dashboard
#projects = Project.find_by_user_id(current_user).page(params[:page]).per(10)
end
I think it is because the #projects is only a couple of records which is less than the 10 specified in .per
I tried adding a #projects.count or #projects.size but I get the error undefined method 'size' for #<Project:0x007f8c996865f0>
def dashboard
#projects = Project.find_by_user_id(current_user)
if #projects.size > 10
#projects.page(params[:page]).per(10)
end
end
What the hell am I doing wrong!? haha
I am guessing I can fix this in the first instance instead of trying to fix the second or third options. Any help would be greatly appreciated.
The issue is Project.find_by_user_id(current_user) returns an Array, not an ActiveRecord::Relation
You should do something like:
current_user.projects.page(params[:page]).per(10)
If your relationships are correctly setup.
Or:
Project.where(user_id: current_user.id).page(params[:page]).per(10)
I'm using a meta_search on my rails 3 app. By default (before pressing a search button) meta_search returns all elements of searching model. and I want to set 0 result before user pressing a search button or if search params is blank.
I am using meta_search as follows:
def index
#search = Article.search(params[:search])
if params[:search].blank?
#places = nil
else
#places = #search.all
end
end
What is the best way to set a 0 result if search params is blank ?
Thanks
I don't think that's something that Meta Search really provides out of the box but you can always cheat it.
def index
#search = Article.search(params[:search].presence || {:id_lt => 0})
#places = #search.all
end
In my opinion, your solution is good enough. It's clear about what it's doing and it doesn't access the database unnecessarily. But the code can be improved to:
def index
#search = Article.search(params[:search])
#places = #search.search_attributes.values.all?(&:blank?) ? [] : #search.all
end
Checking the hash for blank is not the way to do it. A hash like {'name_contains' => ''}, which is what you get if the form submitted is blank, will return false.
Also it's better to set #places to an empty array rather than nil. This way you don't have to check for nil and your loop will still work.