Rails 4 and gem sunspot cannot order correctly - ruby-on-rails

Im getting this error:
Sunspot::UnrecognizedFieldError in SitesController#products
No field configured for Product with name 'created_at'
here is my model Product.rb
class Product < ActiveRecord::Base
searchable do
text :name
text :description
text :specification
string :name
end
end
and here is a mehod in my controller:
def list_all_products
#search = Product.search do
fulltext params[:search]
order_by :created_at, :desc
end
#products = #search.results
end
the name field in my table products is a string. I defined in searchable products both for text and string. Why I still getting an error like this? thank you.

just add time :created_at in your model
class Product < ActiveRecord::Base
searchable do
text :name
text :description
text :specification
time :created_at
string :name
end
end

Related

Association type mismatch in Rails app

Rails 5.1
My migration file:
class CreateFwExports < ActiveRecord::Migration[5.1]
def change
create_table :fw_exports, id: :string do |t|
t.string :screen_name, index: true, limit: 16
t.string :full_name, limit: 21
t.string :location
t.timestamps
end
end
end
In my helper file, I have the following method:
def process_spreadsheet(number_of_rows, spreadsheet)
for i in 1..number_of_rows do
fw_export_record = FwExport.new(
:screen_name => spreadsheet[i][0].to_s,
:full_name => spreadsheet[i][1].to_s,
:location => spreadsheet[i][2].to_s,
)
fw_export_record.save
end
end
What this method does, is receive a spreadsheet CSV object, and iterates through the data, trying to save each row to the fw_exports table.
The first data row is:
xxxxxxxx,xxxxxxxxxx,"Nottingham, England"
I am getting the following error message:
ActiveRecord::AssociationTypeMismatch (Location(#38400060) expected, got "Nottingham, England" which is an instance of String(#10657520)):
app/helpers/fw_exports_helper.rb:21:in `block in process_spreadsheet'
app/helpers/fw_exports_helper.rb:20:in `process_spreadsheet'
app/controllers/fw_exports_controller.rb:82:in `process_parsed_spreadsheet'
When I looked at the actual MySQL table, here's what I got:
id Primary varchar(255) utf8mb4_unicode_ci No None
screen_name varchar(16) utf8mb4_unicode_ci Yes NULL
full_name varchar(21) utf8mb4_unicode_ci Yes NULL
location varchar(255) utf8mb4_unicode_ci Yes NULL
From the controller:
def fw_export_params
params.require(:fw_export).permit(:screen_name, :full_name, :location)
end
id is generated through a method defined in the concerns section
Any idea why I'm getting the error message?
Edit:
In my fw_exports.rb model, I had the following:
has_one :location
I have a locations table (and model), with the following fields:
t.string :fw_exports_id, index: true
t.string :city
t.string :state
t.string :country
When I commented out, the line in the fw_exports.rb model:
# has_one :location
I stopped getting the above mentioned error, and instead, I am now getting the following error:
NoMethodError (undefined method `each' for "0":String):
app/helpers/fw_exports_helper.rb:21:in `block in process_spreadsheet'
app/helpers/fw_exports_helper.rb:20:in `process_spreadsheet'
app/controllers/fw_exports_controller.rb:82:in `process_parsed_spreadsheet'
Same spot in code, different message.
Add |i| after the do
for i in 1..number_of_rows do |i|
Edit after response in comment:
You don't show the model but probably you have a relationship called location that is conflicting with the field.
As you have:
class FwExport < ApplicationRecord
has_one :location
and assuming that:
class Location < ApplicationRecord
belongs_to :fw_export
so you cannot define :location as a string column in CreateFwExports migration.
First you need to write another migration to remove the column from :fw_exports table:
class RemoveColumnFromFwExports < ActiveRecord::Migration[5.1]
def change
remove_column :fw_exports, :location, :string
end
end
Now rewrite the helper method that would parse the location string from csv into a Location instance and assign it into the FwExport instance:
def process_spreadsheet(number_of_rows, spreadsheet)
1.upto(number_of_rows) do |i|
fw_export_record = FwExport.new(
screen_name: spreadsheet[i][0].to_s,
full_name: spreadsheet[i][1].to_s,
)
fw_export_record.save
# now create the location and associate it to fw_export_record
location = find_or_create_location(spreadsheet[i][2].to_s)
location.fw_exports_id = fw_export_record.id
location.save
end
end
private
def find_or_create_location(s)
city, country = s.split(',').map(&:strip)
Location.find_or_create_by!(city: city, country: country)
end

Rails ActiveAdmin showing attributes from different model

ActiveAdmin.register User do
index do
column :email
column :first_name
column :surname
end
end
app/models/user.rb
has_many :tasks
app/models/task.rb
belongs_to :user
I have all the attributes in the User model. Is it possible to call those attributes in the Task model. I tried to look up for it but couldn't find anything suitable. For example:
ActiveAdmin.register Task do
index do
column :email
column :first_name
column :surname
end
end
Yes, you can! For example:
ActiveAdmin.register Task do
index do
column "Email" do |task|
task.user.email
end
column "First name" do |task|
task.user.first_name
end
end
end

rails sunspot searchable enum

How to make enum in rails searchable with sunspot?
enum type: [ :restaurant, :travel, :hotel ]
searchable do
text :name, :boost => 5
text :description
integer :type
time :created_at
end
my controller:
#search = Product.search do
fulltext params[:search]
end
still no results, any idea?
You can change the searchable field definition from an integer to a string, and use with(:field, params[:search_query]).
model:
searchable do
string :enum_field
end
controller:
#search = Product.search do
with(enum_field: params[:search_query])
end
EDIT: Also, it just occurred to me that you might need to rename your enum column, as ActiveRecord uses type to signify Single Table Inheritance.

Showing index to current user, only their information

I have a model Order. In the index, I want the current_user to see the index with only their orders. Order belongs_to :admin_user. AdminUser has_many :orders. I am using activeadmin in my app, if that makes a difference. I am getting this error:
Couldn't find Order without an ID
The line giving the error is the second line in my order controller.(redacted unnecessary info)
index do
#order = Order.where(admin_user_id: current_admin_user.id, order_id: resource.id)
column "ID" do |order|
link_to order.id, admin_order_path(order)
end
column "Proof" do |order|
image_tag order.proof_url(:proof).to_s
end
column "Name" do |order|
link_to order.name, admin_order_path(order)
end
column(:customer, :sortable => :customer_id)
column "Category", :order_category
column "Status", :order_status
column "Priority", :order_priority
column "Due Date", :end_date
default_actions
end
here is my order model requested by #jamesw
class Order < ActiveRecord::Base
attr_accessible :color_back, :color_front, :color_sleeve, :end_date, :name, :start_date, :whiteboard, :customer_id, :order_category_id, :order_type_id, :order_status_id, :order_priority_id, :print_location_id, :artwork, :proof, :line_items_attributes, :assignee_id, :admin_user_id
mount_uploader :artwork, ArtworkUploader
mount_uploader :proof, ProofUploader
has_many :line_items
belongs_to :assignee, :class_name => "AdminUser"
belongs_to :customer
belongs_to :order_category
belongs_to :order_type
belongs_to :order_status
belongs_to :order_priority
belongs_to :print_location
belongs_to :admin_user
accepts_nested_attributes_for :line_items, :allow_destroy => true
scope :owned_by, lambda { |user| includes(:assignee).where("admin_users.id = ?", user.id) }
def default_values
if new_record?
self.start_date ||= Date.today
self.number ||= (Order.maximum(:number) + 1 rescue 1)
end
end
end
It looks like you're trying to filter the Orders table by order_id. Unless you've built your DB in a non-standard manner, the ID field of the orders table would typically be id (not order_id).
That issue aside, I doubt you want to be passing in an order id for the index action since that would only return a single record, and by it's nature the index action should list many records (in your case, all records for the current_admin_user).
If neither of those issues solve your problem, try commenting out the lines 1 by 1.
Try to add this controller method
ActiveAdmin.register Order do
controller do
def scoped_collection
Order.where(:admin_user => current_admin_user.id)
end
end
end
see more here:
Two pages for the same resource - ActiveAdmin
I fixed the issue by taking the line in question out and using scope_to :current_user. I am wondering though, how to add a conditional statement to still allow the admin to view this? here is a look at the controller now.
scope_to current_user
index do
column "ID" do |order|
link_to order.id, admin_order_path(order)
end
column "Proof" do |order|
image_tag order.proof_url(:proof).to_s
end
column "Name" do |order|
link_to order.name, admin_order_path(order)
end
column(:customer, :sortable => :customer_id)
column "Category", :order_category
column "Status", :order_status
column "Priority", :order_priority
column "Due Date", :end_date
default_actions
end

Rails db relations: Post.category.name = ? (undefined method `name')

Every post has only one category, and i need to access category's name by something like
p = Post.new
p.category.name = "tech"
p.save
How to do that?
class Category < ActiveRecord::Base
has_many :posts, :dependent => :destroy
attr_accessible :name, :image
end
Post.rb
class Post < ActiveRecord::Base
belongs_to :category
attr_accessible :category_id, :name, :text, :lang, :image
end
Schema.rb
create_table "categories", :force => true do |t|
t.string "name"
t.string "image"
end
Your example contains a problem.
p = Post.new
p.category.name = "tech"
p.save
First, you create a new post. Second, you want to assign a name to the category of the post, BUT there is no category assigned. This results in a call like post.nil.name where nil would be the category object, if assigned, which isn't the case. Since nil has no method name, you get the described error undefined method name for nil class.
To solve this, you first need to assign a category to work on.
p.category = Category.first or p.category_id = 1. After that, p.category will return the category object, therefore p.category.name is valid then because it is called on a category object and not on nil.
tl;dr:
p = Post.new
p.category # => nil
p.category.name # throws an error
p.category = Category.first
p.category # => <#Category ...>
p.category.name # => 'actual name of category'
p.category.name = 'foo' # works now
The problem is that you need/want to explicitly build the category record if it doesn't exist.
To solve the problem, I'd think about creating a category_name= method in Post:
A category_name= settor would also take care of the "law of Demeter" issue
class Post < ActiveRecord::Base
belongs_to :category
attr_accessible :category_id, :name, :text, :lang, :image
attr_accessible :category_name=, :category_name
def category_name=(name)
self.category = Category.find_or_create_by_name(name)
end
def category_name
category && category.name
end
end
See also "Association Extensions" in the ActiveRecord docs for another way to do this.

Resources