CastAboutFor
CastAboutFor allows you easily and reliably query ActiveRecord.
Installation
Install this gem by adding this to your Gemfile:
gem 'cast_about_for'Then run:
bundle installUpdating is as simple as bundle update cast_about_for.
Usage
Setting the Query Column
First, you must set some query colums in your model using the cast_about_for_params macro:
class Product < ActiveRecord::Base
  cast_about_for_params equal: ['name', 'sex']
  # ...
endStart the Query:
You can always use the #cast_about_for class method to query:
def index
  @products = Product.cast_about_for(params)
endWant to count records? Simple:
  Product.cast_about_for(params).countcast_about_for_params Configure
Equal
If you want to use a column query the SQL look like SELECT "products".* FROM "products" WHERE (name = 'iPhone'), you can pass it as an option:
# params = {name: 'iPhone'}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params equal: ['name']
  # ...
endOr you want to alias of the name argument in params
# params = { nick_name: "iPhone"}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params equal: [{name: "nick_name"}]
  # ...
endAnd you have other alias arguments , you can do it like below.
# params = { nick_name: "iPhone", info: "sales", price: "600"}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params equal: [{name: "nick_name"}, {information: "info"}, price]
  # ...
endLike
If you want to use a column query the SQL look like SELECT "products".* FROM "products" WHERE (introduce LIKE '%To%'), you can pass it as an option:
# params = {introduce: 'To'}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params like: ['introduce']
  # ...
endSuck as Equal. If you want alias of introduce argument, you can
class Product < ActiveRecord::Base
  cast_about_for_params like: [{introduce: 'intr'}]
  # ...
endAfter
If you want to use a column query the SQL look like SELECT "products".* FROM "products" WHERE (production_date >= '2016-07-05 13:09:00'), you can pass it as an option:
# params = {production_started_at: '2016-07-05 13:09:00', by_time: 'production_date'}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params after: { field: 'by_time', time: "production_started_at" }
  # ...
endIn addition, if your params not include by_time option. Like params = {production_started_at: '2016-07-05 13:09:00'}, the query column will be set the default column created_at.
If you want to use multiple column query the SQL look like SELECT "products".* FROM "products" WHERE (production_date >= '2016-07-05 13:09:00') AND (created_at >= '2016-07-04'), you can do it like this:
# params = {production_started_at: '2016-07-05 13:09:00', by_time: 'production_date', create_field: 'created_at', production_created_at: '2016-07-04'}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params after: [{field: 'by_time', time: "production_started_at"}, { field: 'create_field', time: "production_created_at"}]
  # ...
endIf you want more columns to query, you can code it like this pattern: cast_about_for_params after: [{field: 'by_time', time: "production_started_at"}, { field: 'create_field', time: "production_created_at"}, {field: '..', time: '..'}, {...}, ...]
If you want to set the field exact column you can do it like this:
# params = {production_started_at: '2016-07-05 13:09:00'}
# Product.cast_about_for(params) # The SQL: `SELECT "products".* FROM "products" WHERE (production_date >= '2016-07-05 13:09:00')`
class Product < ActiveRecord::Base
  cast_about_for_params after: [{field: {exact: "production_date"}, time: "production_started_at"}]
  # ...
endBefore
Just like the above After.
If you want to use a column query the SQL look like SELECT "products".* FROM "products" WHERE (production_date <= '2016-07-05 13:09:00'), you can pass it as an option:
# params = {production_ended_at: '2016-07-05 13:09:00', by_time: 'production_date'}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params before: {field: 'by_time', time: 'production_ended_at'}
  # ...
endIn addition, if your params not include by_time option. Like params = {production_ended_at: '2016-07-05 13:09:00'}, the query column will be set the default column created_at.
If you want to use multiple column query the SQL look like SELECT "products".* FROM "products" WHERE (production_date <= '2016-07-05 13:09:00') AND (created_at <= '2016-07-04'), you can do it like this:
# params = {production_ended_at: '2016-07-05 13:09:00', by_time: 'production_date', create_field: 'created_at', production_created_at: '2016-07-04'}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params after: [{field: 'by_time', time: "production_ended_at"}, { field: 'create_field', time: "production_created_at"}]
  # ...
endIf you want more columns to query, you can code it like this pattern: cast_about_for_params after: [{field: 'by_time', time: "production_ended_at"}, { field: 'create_field', time: "production_created_at"}, {field: '..', time: '..'}, {...}, ...]
If you want to set the field exact column you can do it like this:
# params = {production_ended_at: '2016-07-05 13:09:00'}
# Product.cast_about_for(params) # The SQL: `SELECT "products".* FROM "products" WHERE (production_date <= '2016-07-05 13:09:00')`
class Product < ActiveRecord::Base
  cast_about_for_params after: [{field: {exact: "production_date"}, time: "production_ended_at"}]
  # ...
endEnum
If you have a column use enum, you can pass it as an option:
# params = {category: "food"}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  enum category: {food: 0}
  cast_about_for_params enum: ['category']
  # ...
endSuck as Equal. If you want alias of category argument, you can
# params = {other_name: "food"}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params enum: [{category: 'other_name'}]
  # ...
endComparison
If you want to compare a column, the sql like this: The SQL: SELECT "products".* FROM "products" WHERE (weight >= '100' AND weight <= '1000')
you can do it like this:
# params = {weight_min: 100, weight_max: 1000}
# Product.cast_about_for(params)
class Product < ActiveRecord::Base
  cast_about_for_params comparison: [{"weight >= ?" => "weight_min"}, {"weight <= ?" => "weight_max"}]
end###Includes
If you want to includes other models, you can do it like this
class Product < ActiveRecord::Base
  cast_about_for_params includes: [:user, :items]
#This will make `product` include `user` and `items` automatically
#Like:  Product.includes(:user, :items)
end###Joins
If you want to join a model you can do it like this:
Example 1 
class Product <  ActiveRecord::Base
  cast_about_for_params joins: [{user: [equal: :name]}]
  
end
# params = {name: "user"}
# Product.cast_about_for(params)
# It will be generates like this: Product.joins(:user).where("users.name = ?", "user")
# The sql would like this: `SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" WHERE (users.name = 'user')`
If you want to query the condition of "LIKE", do it like this
class Product <  ActiveRecord::Base
  cast_about_for_params joins: [{user: [like: :name]}]
  
end
Then the sql would be like this:  `SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" WHERE (users.name Like 'user')`
--------
Example 2
If you want to nickname the `name` of the params like: 
# params = {user_name: "user"}
# Product.cast_about_for(params)
class Product <  ActiveRecord::Base
  cast_about_for_params joins: [{user: [equal: {name: :user_name}]}]
  
end
# Also will generates like this: Product.joins(:user).where("users.name = ?", "user") 
# The sql would like this: `SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" WHERE (users.name = 'user')`
--------
Example 3
If multiple user columns that you want to query, you can do it like this:
# params = {name: "user", age: 18}
# Product.cast_about_for(params)
class Product <  ActiveRecord::Base
  cast_about_for_params joins: [{user: [equal: [:name, :age]}]
  
end
# Also will generates like this: Product.joins(:user).where("users.name = ? AND users.age = ?", "user", "18") 
# The sql would like this: `SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" WHERE (users.name = 'user' AND users.age = 18)`
If you want to nickname the params:
# params = {user_name: "user", user_age: 18}
# Product.cast_about_for(params)
class Product <  ActiveRecord::Base
  cast_about_for_params joins: [{user: [equal: [{name: :user_name}, {age: :user_age}]}]
  
end
--------
Example 4
You can use the `equal` and `like` at the same time:
class Product <  ActiveRecord::Base
  cast_about_for_params joins: [{user: [equal: :age], [like: :name]}]
  
end
`OR`
class Product <  ActiveRecord::Base
  cast_about_for_params joins: [{user: [equal: [:age, :height]], [like: [:name, :roles]]}]
  
end
--------
Example 5
Nested joins:
Now, I have `product` `user` `company` models, 
class Product <  ActiveRecord::Base
  belongs_to :user
end
class User <  ActiveRecord::Base
  belongs_to :company
  has_many :products
end
class Company <  ActiveRecord::Base
  has_many :user
end
I have company `name`, and now I want to query the products through the user who belong to the company, so I can do it like this:
class Product <  ActiveRecord::Base
  cast_about_for_params joins: [{{user: :company} => [like: {name: :company_name}]}]
  
end
# params = {company_name: "Teo"}
# Product.cast_about_for(params)
# The sql would like this:  SELECT "products".* FROM "products" INNER JOIN "users" ON "users"."id" = "products"."user_id" INNER JOIN "companies" ON "companies"."id" = "users"."company_id" WHERE (companies.name LIKE 'Teo')Advanced Usage
JSON API
If you are using JSON API, you can set in the #cast_about_for:
  Product.cast_about_for(params, jsonapi: true) # JSON APICustom Query by Block
If want to find products where belong to some people, you can do it like:
  params = { user_name: 'hello', age: 20 }
  Product.cast_about_for(params, jsonapi: true) do |products, cast_params|
    products = products.joins(:user).where("users.name Like ?", "%#{cast_params[:user_name]}%") if cast_params[:user_name].present?
    products = products.joins(:user).where("users.age = ?", cast_params[:age]) if cast_params[:age].present?
  endCollaborators
Thank you to the following people:
- The creators of the by_star gem
License
The gem is available as open source under the terms of the MIT License.