Hi I have just followed Ryan Bates guide to loading data from the server as the client interacts with the datatable.
http://railscasts.com/episodes/340-datatables?view=asciicast
In his ProductsDatatable class he defines a sorting function:
def sort_column
columns = %w[name category released_on price]
columns[params[:iSortCol_0].to_i]
end
Basically the column name is used to query the database, so "name", "category", etc are all attributes to the product model. So an SQL SELECT statement is generated with Name or Category being used for sorting ASC or DESC.. and so on...
If I have data being displayed in a column that does not map explicitly to a attribute.. such as product.reviews.count, how would I then allow sorting of that column?
You would need something like this
def sort_column
columns = ['name', 'category', 'released_on,' 'price', 'number_of_reviews]
columns[params[:iSortCol_0].to_i]
end
But this means that you need to change the way you get your data, for example:
Product.where(…).select('name, category, count(reviews.id) as number_of_reviews').group('name, category').includes('reviews')
I haven't been able to test the definition of columns, you may have to use reviews.number_of reviews instead
I know this is a really old post (by now), but just wanted to let you know that this gem: https://github.com/antillas21/ajax-datatables-rails can help you jumpstart creating datatables classes easily, as described in the Railscast you mention (it's actually based in this same pattern).
What the gem does is to let you focus on writing the query to retrieve your model(s) data from the db and how to expose it in the JSON that jquery.dataTables needs.
Take it for a spin.
Related
I am using the textacular gem to implement fuzzy search in my Rails application, and I cannot figure out how to perform a search on multiple tables at once. Here's an example query that searches multiple tables WITHOUT textacular:
#results = Owner.includes(:car => :company).where("name LIKE ? OR cars.name LIKE ? OR companies.name LIKE ?", sql_query, sql_query, sql_query).references(:cars, :companies)
As you can see, this query searches the Owner, Car, and Company tables. The farthest I got with textacular is this:
#results = Owner.includes(:car => :company).references(:cars, :companies).fuzzy_search({name: sql_query})
The above query only searches the Owner table, though. I've tried doing the following to get it to search the Companies table as well:
#results = Owner.includes(:car => :company).references(:cars, :companies).fuzzy_search({name: sql_query, "companies.name" => sql_query})
This doesn't work because it tries searching the owners.companies.name field, which of course does not exist. I want it to search the companies.name field in addition to the owners.name field. Does anyone know how to perform a fuzzy search on multiple tables using textacular?
I figured it out! You need to add the joined table name as a nested hash. Let's say I want to search by the name fields of the Owner model AND the Car model:
#results = Owner.includes(:car).references(:cars).fuzzy_search({name: sql_query, cars: { name: sql_query}})
The cars table specified in the fuzzy_search method refers to the name of the table, NOT the name of the association.
I got inspiration from this old Rails commit from 2008, which made me realize that the conditions you can use in any standard Rails query are available in the fuzzy_search method.
Not sure if you're wedded to textacular but from their docs it looks like you can only search by one model.
I've used PgSearch before and and it's pretty robust, you can search across models.
I'm looking to rewrite my project in Rails. It's currently written in PHP (CodeIgniter), I've come to the point where I'm writing more libraries and core extensions than I'm writing new code. I've been looking at some Rails tutorials and I'm liking what I see so far (even though I feel you have less control of what's been passed around). However it seems there's little information out there (maybe I'm not looking in the right places) on database tables without models.
For example, I need a table called user_verification_token
CREATE TABLE IF NOT EXISTS `user_verification_token` (
`user_id` int(11) NOT NULL,
`token` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`is_used` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
It doesn't make sense for me to create a model for this, right?
First question: How do I generate a migration to create a table alone without any model?
Second question: When this table is filled with data, how do I associate with it. e.g. Associate it with the User model (if possible)/a user object so I can find a user by a token (provided is_used = 0) and return the user's data?
I apologize in advance if this is a newb question, I can do all these comfortably with PHP but I don't know how to do this on Rails.
You need a model for this table. It does make sense for you to have a model for the user_verification_token table. In order to get the associations and all the other functionality you'll want from this data, you need to create a model and the associations for it.
To answer the first question: run rails generate migration your_migration_name
For the activity_type table you mention in the comment on the original question, you might be interested in the RailsLookup gem to help automate some of the work required to make good use of lookup tables in Rails. There is a blog post describing it and the source can be found on GitHub
Your current scenario does require a model, although when you need to store data like categories e.g Sports(football,tennis,cricket,swimming,basketball,etc), you can store them as constants in your config->initializers->constant eg. SPORT_CATEGORIES = [["Football","football"],["Tennis","tennis"],etc], alternatively if you have more cols to store you can create a model then create the default rows as you would in a php .sql file but in ruby of course :) For example:
sport_categories = [
{:category => "football", :category_type => "manly" },
{:category => "Tennis", :category_type => "manly" },
etc
]
sport_categories.each do |attributes|
Model_name_here.find_or_initialize_by_category(attributes[:category]).tap do |p|
p.category_type = attributes[:category_type]
p.save!
end
end
Then you run rake db:seed.
I will suggest you to create model for this, as you will have complete access to user_verification_token table via UserVerificationToken model which will be associated to user.
Create a model because all the validations can be done in a model.
eg:validates :user_id. So there is no need to include those constraints while creating the table
I am writing a Rake task to populate a database for development purposes to have some data to work with. ( but In test I am using FactoryGirl, so not talking about that. )
So let's say I have two sample Organizations in my demo database, so I have defined them like this:
sample_organizations = [ '37 Signals', 'Fog Creek']
and then a small method to populate the DB like this:
def create_organizations
sample_organization.each { |item|
Organization.first_or_create(
name: item,
time_zone: 'Central'
)
}
end
so the good thing is that two months from now if I wanted to add a third organization I just go to top of my code and hand type another organization name in that array. Method still works and creates it.
Now here starts the question: I have more tables to populate! For example Summaries table which is hanging off of Organization table, so each organization can have many Summaries, so we have an organization_id foreign key in Summary table to fill too.
But still I want to have a method like create_summaries that does something similar to create_organization method above, but this time fills in Summaries table, and the tricky part is to fill in that organization_id field of the table.
How should I approach this?
Let's say Summaries table has these fields: id (auto generate by Rails) , organization_id, name, member_count
Try using Populator gem for tasks like this. It is easy to use, and you can generate complex structures. Screencast.
As you can't use those, use select a random parent object, or specify one by name in a hash.
summaries = [{:name => "foo", :organization => "bar"}]
Is there any gem/plugin for ruby on rails which gives the ability to define custom fields in a model at runtime with no need to change the model itself for every different field.
I'm looking for something like Redmine acts_as_customizable plugin which is packaged as a gem usable in the rails way, i.e.
gem 'gemname'
rails g something
rails db:migrate
class Model < ActiveRecord::Base
acts_as_something
end
Here are the CustomField and the CustomValue classes used in Redmine.
Edit:
Since my question is not clear I add a brief use case which explains my need better:
I want users to be able to design their own forms, and collect data
submitted on those forms. An important decision is the design of how
these custom dynamic records are stored and accessed.
Taken from here, in this article approach the problem with different ideas, but they all have drawbacks. For this reason I'm asking if the issue has been approached in some gem with no need to rethink the whole problem.
I'm not aware of a gem that does this, but serialize works quite well and it's a built-in. You get a NoSQL-ish document store backed by JSON/YAML.
If you allow user to create a custom form, you can pass nested arrays et cetera directly into the attribute. However, if you need to validate the structure, you're on your own.
I'm afraid it could be tricky and complicated to do it in ActiveRecoand (generally in standard relational database). Take a look at http://mongoid.org/docs/documents/dynamic.html - this mechanism is using nosql feature.
You can also may try the following trick:
1/ Serialize a hash with your custom fields in the database column, for example { :foo => 'bar', :fiz => 'biz' }
2/ After load a record from database do some metaprogramming and define corresponding methods on the record's singleton class, for instance (assume that custom fields are stored and serialized in custom_fields column):
after_initialize :define_custom_methods
# ..or other the most convinient callback
def define_custom_methods
# this trick will open record's singleton class
singleton_class = (class << self; self; end)
# iterate through custom values and define dynamic methods
custom_fields.each_with_key do |key, value|
singleton_class.send(:define_method, key) do
value
end
end
end
Since rails 3.2 you can use store method. Just include following in your model:
store :properties, accessors: [:property1, :property2, :property3...]
You only need to change your model once (to add properties field to db table). You can add more properties later without altering the schema.
The way this works is by serializing properties hash into YAML and saving it into database. It it suitable for most cases, but not if you'd like to use these values in db queries later.
I don't know a gem, but this can be accomplished be creating a table called custom_fields with a name column and possibly a datatype column if you wanted to restrict fields by datatype.
Then you create a join table for a custom field to your desired table and a value and do whatever validations you want.
I am using Rails and postgres.
I have a couple of models using STI and i was wondering where i should put indexes on the tables and why?
For example lets say i have the following setup:
class Comment < AR; end
class MovieComment < Comment; end
class MagazineComment < Comment; end
# Fake Comment Table
id:integer
title:string
body:text
type:string
Thanks!
On the type field, if you want only one of MovieComment or MagazineComment. If you don't do that, you won't need the index here. I'm not sure if AR does use type every time, but just to make sure.
Because the id field is a primary key, an index should already be there.
If you want to query by both type and id make sure you have a combined index.
On the other fields: Depends what you query on, but I suppose you want to retrieve these only.
In general, you need indices in the columns that you will use when performing queries.
If you do MovieComment.find(10), the database will use the index in the id field that Rails will add automatically for you. Same if you do Comment.find(30): Rails will retrieve the commend with id 30 using the index, then it will read the type column and it will return a MovieComment or a MagazineComment.
If you are going to add a feature to search by title, for instance, you will have to create an index in this column as well. In this case, probably a :fulltext index.
An Index in the type column would make a query like MagazineComment.all faster because it is equivalent to Comment.where(type: 'MagazineComment').all, but it is probably not worth it.