Hot questions for Using Spree in ransack

Question:

Ransack search work fine with some attributes:

Spree::Callback.all.ransack(name_cont: 1).result

SELECT "spree_callbacks".* FROM "spree_callbacks" WHERE ("spree_callbacks"."name" ILIKE '%1%')

And don't work with others...

Spree::Callback.all.ransack(phone_cont: 1).result

SELECT "spree_callbacks".* FROM "spree_callbacks"

What's wrong?

P.S. Callback is my custom model under Spree module

And example of Callback object:

Spree::Callback.first
  Spree::Callback Load (1.4ms)  SELECT  "spree_callbacks".* FROM "spree_callbacks"  ORDER BY "spree_callbacks"."id" ASC LIMIT 1
=> #<Spree::Callback:0x00000009eb68c0 id: 39, 
phone: "123", 
comment: "", 
created_at: Wed, 12 Jul 2017 03:37:03 UTC +00:00, 
updated_at: Wed, 12 Jul 2017 03:41:34 UTC +00:00, 
name: "123", 
processed: true>

Answer:

@nuT707 - To be able to search by using ransack gem, you will first have to whitelist all those fields on which you wanna perform search. So in you callback.rb model add the following line -

self.whitelisted_ransackable_attributes |= %w[phone]

and now try to search with ransack.

Hope this helps you.

Question:

I'm trying to run searches using ransack queries, but I'm getting invalid search term results on the following /api/v1/products?q[classifications_taxon_id_eq]=3. Can someone please tell me what I'm doing wrong?

I deliberately set ransack to not ignore invalid terms, just to try to figure out what's going on.

The error I get is something like:

Invalid search term classifications_taxon_id_eq

Answer:

You need to whitelist classifications in the product model:

After that in the classification model, you need to whitelist the taxon attribute.

https://github.com/spree/spree/blob/master/core/app/models/spree/product.rb#L117

Question:

Trying to learn Ruby and Spree

I've got a query in my controller that's running fine:

@products = Spree::LineItem.select("spree_line_items.id, 
spree_variants.sku, spree_products.name, spree_line_items.quantity")
.joins(:order).joins(:variant).joins(:product)
.where(spree_orders: {state: 'complete', shipment_state: 'ready'})

When I run the query in my view

<% @products.each do |lineItem| %>
<%= lineItem.id %><br>
<% end %>

This works fine and spits out all of the ID's but I'm wanting to output the other bits, Sku, Name and Quantity which are all from other tables. How do I bring them in here?

If I reference them the same as the ID I get a DelegationError.


Answer:

To answer your query, you can do

@products = Spree::LineItem.select("spree_line_items.id, 
spree_variants.sku AS variant_sku,
spree_products.name as product_name,
spree_line_items.quantity as quantity")
.joins(:order).joins(:variant).joins(:product)
.where(spree_orders: {state: 'complete', shipment_state: 'ready'})

Then access sku as lineItem.variant_sku, name as lineItem.product_name and quantity as lineItem.quantity.

But the appropriate way to achieve this is

Spree::LineItem.joins(:order).includes(variant: :product)
.where(spree_orders: {state: 'complete', shipment_state: 'ready'})

And access attributes as lineItem.sku, lineItem.name, lineItem.quantity

We can do this because sku and name are delegated to variant in line_item model. This the same reason that you are getting DelegationError.

Question:

I am trying to find all variants in spree where is_master is false but ransack is not working as expected. The reason I am using ransack is so I can run this search over the spree api so I can make a request like /api/v1/variants?q[is_master_true]='0' to get all the non master variants.

In the documentation

>> User.ransack(awesome_false: '1').result.to_sql
=> SELECT "users".* FROM "users"  WHERE ("users"."awesome" = 'f')

In practice

> Spree::Variant.ransack(is_master_false: '1').result.to_sql
=> "SELECT \"spree_variants\".* FROM \"spree_variants\" WHERE \"spree_variants\".\"deleted_at\" IS NULL" 

The is_master_false is ignored in the sql

Another search like sku_eq works fine

> Spree::Variant.ransack(sku_eq: '17636').result.to_sql
=> "SELECT \"spree_variants\".* FROM \"spree_variants\" WHERE \"spree_variants\".\"deleted_at\" IS NULL AND \"spree_variants\".\"sku\" = '17636'" 

Why does is_master_false: '1' do nothing to the sql query created instead of finding records where is_master = false?


Answer:

@Qwertie: For ransack search you need to first whitelist all the attributes on which you want to perform ransack search.

Currently, in the Variant model only weight sku are whitelisted.

So you need to whitelist is_master field yourself

For doing just create a decorator for variant in spree/models with name variant_decorator.rb and write

Spree::Variant.class_eval do
  ### WHITELISTED ATTRIBUTES ###
  self.whitelisted_ransackable_attributes |= ['is_master']
end

Or in spree.rb add Spree::Variant.whitelisted_ransackable_attributes.push('is_master')

Now restart your server or rails console and try it out.