When we use ActiveRecord, we can use:
User.find(:first, :conditions=>["name=?", name])
It looks like ActiveRecord are using 'prepared statement', but after looking into the code, I found ActiveRecord just use String.dup and connection.quote() to adjust the content to build a sql, not like Java.
So, there is no real prepared statment in raiils? And why rails doesn't provide it?
If by prepared statement you mean a piece of SQL that is held in a compiled form for more efficient execution, then you're correct: it's not something implemented in Rails. There are several reasons for this:
Rails is the web framework - it doesn't know or care about databases. By default, Rails uses
ActiveRecord for object-relational mapping. You can change this if you want to - it doesn't have to be a RDBMS even.
ActiveRecord doesn't know about specific database platforms. For that it relies on "adapters", which translate AR's requirements into platform-specific SQL.
Some RDBMSs that have AR adapters support prepared statements (or equivalent) but others don't.
Rails 3.1 (or greater) supports prepared statements. Every new query you make will be added to pool of prepared statement. If you are are using MySql DB it still won't support prepared statement because using prepared statements in MySql reduces the performance compare to without prepared statement. Here is the nice article by Pat Shaughnessy on this.
In many (most?) ways, a DB View is a prepared statement. And it is easy to use views with ActiveRecord. Just declare the view in your DB (I use rake tasks) and then access it via ActiveRecord.
Works great for read-only access to complicated SQL. Saves the DB from many of the steps required to parse/compute SQL.
Related
I am having a database in Ruby on Rails application using SQLite3. Knowing my table, is there an open source project which can provide me an easy way of creating sqlite queries?
For example, based on the table names and order, I have a the available joins, and then I can add my conditions based on my variables.
Probably not.
Active record will provide you a lot of the functionalities you need to query, create and update records. It's not all that good at generating joins though.
The thing is, only you know the query you need to generate, hence there are very few "one-size-fits-all" query generator. It's a bit like asking "is there a Ruby code generator for generating my application". Well no, because only you knows what needs to be coded.
I tempted to say, keep your infrastructure simple, code the few queries you need rather than "rocket-science" a fancy generator that'll be hard to maintain. If in then end you need to generate a query from various arguments, concatenate strings and you'll get there faster than the time you'd take to research a generator.
I am making an application with very huge data and multiple joins. Is it a bad practice to right away use the full sql string in rails? What are the downsides of writing the full sql query in rails?
It's only bad practice if you do it without understanding the alternatives.
That said there is rarely a reason to do this. The framework encapsulates it for you and the benefit is that you have to write less code. The other benefit is database independence. The more direct queries you write, the more likely you'll write something that will break when you switch database engines.
It is easy to test. If you are using the framework properly (i.e. optimizing ActiveRecord as you will find discussed in numerous articles) and still feel like your queries are too slow...you can always benchmark direct queries.
But not knowing how to do something using ActiveRecord associations is not a good reason to resort to direct SQL.
http://guides.rubyonrails.org/association_basics.html
SQL is not a 'bad practice' per se. Database systems have plenty of native SQL ways of doing things that would be much slower to execute and more complex to write and maintain if written in Ruby. Like Oracle's Analytic Functions.
That said, ActiveRecord is pretty easy to write and you probably aren't going to get a performance boost just by using a SQL query. At least not if the query you write resembles the query ActiveRecord would have written anyway! ;)
Perhaps you should try to work with ActiveRecord and only resort to SQL if you hit problems you can't solve another way. That way you keep your code simple until you need to do it another way (i.e. don't 'optimise early').
I generally try to make things work in ActiveRecord (or DataMapper or Sequel or whatever), but I have definitely resorted finder_sql when the job needed doing quickly and I couldn't get where I wanted to go using the ORM's 'sugar'. Other times I have based a rails object on a single massive view in the database.
Hope this helps.
:D
If you need more powerfull syntax than provides standard ActiveRecord module, see meta_where gem.
My development database is SQLite but I deploy my app to Heroku and they are using PostgreSQL.
Now sometimes I have two different results coming out if I perform searches because PostgreSQL is case-sensitive but SQLite is not.
Shouldn't Rails standardize these things? What methods should I use to solve that?
Here is how to fix it with raw SQL
Case insensitive searching in Postgres:
use ilike instead of like (case-insensitive like)
if you want to use =, make both sides either UPPER or LOWER
Another DDL way of handling this is the citext data type, or case-insensitive TEXT.
There are many relatively common things that ActiveRecord doesn't handle, and LIKE matching is one of them. Here is how to achieve this using straight Arel instead.
Model.where(
Model.arel_table[:title].matches("%#{search_term}%")
)
You can install Arel-Helpers to make this a little easier
Model.where(Model[:title].matches("%#{search_term}%"))
I previously recommended Squeel for this, but the original creator has stopped supporting it and there doesn't seem to be a full-time developer maintaining it. And since it plays around with private ActiveRecord APIs, it needs constant tending.
I would like to use a delimited text file (xml/csv etc) as a replacement for a database within Ruby on Rails. Solutions?
(This is a class project requirement, I would much rather use a database if I had the choice.)
I'm fine serializing the data and sending it to the text file myself.
The best way is probably to take the ActiveModel API and build your methods that parse your files in the appropriate ways.
Here's a good presentation about ActiveModel and ActiveRelation where he builds a custom model, which should have a lot of similar concepts (but different backend.) And also a good blog post by Yehuda about the ActiveModel API
Have you thought of using SQLite? It is much better solution.
It uses a single file.
It is way faster than doing the serialization yourself.
It is zero configuration. Very simple to use.
You get ACID compliance, transactions sub selects etc etc.
MySQL has a way to store tables in CSV. It has some pretty serious limitations, but it sounds like your requirements demand something with some pretty serious limitations anyway.
I've never set up a Rails project that way, and I don't know what it would take, but it seems like it might be possible.
HSQLDB seems to work by storing data on disk as a SQL script that creates your database. It records changes in memory and a log file, and when you shut down it recreates a single SQL script again. I've not used this one myself.
HSQLDB doesn't appear to be one of the supported databases in Rails. I don't know what it would take to add support for a new database.
I'm considering using Sequel for some of my hairier SQL that I find too hard to craft in Active Record.
Are there any things I need to be aware of when using Sequel and ActiveRecord on the same project? (Besides the obvious ones like no AR validations in sequel etc...)
Disclaimer: I'm the Sequel maintainer.
Sequel is easy to use along side of or instead of ActiveRecord when using Rails. You do have to setup the database connection manually, but other than that, the usage is similar. Your Sequel model files go in app/models and work similarly to ActiveRecord models.
Setting up the database connections isn't tedious, it's generally one line in environment.rb to require sequel, and a line in each environment file (development.rb, test.rb, production.rb) to do something like:
DB = Sequel.connect(...)
So it's only tedious if you consider 4 lines of setup code tedious.
Using raw SQL generally isn't a problem unless you are targeting multiple databases. The main reason to avoid it is the increased verbosity. Sequel supports using raw SQL at least as easily as ActiveRecord, but the times where you need to use raw SQL are generally fairly rare in Sequel.
BTW, Sequel ships with multiple validation plugins. The validation_class_methods plugin is similar to ActiveRecord validations, using class methods. The validation_helpers plugin has a simpler implementation using instance level methods, but both can do roughly the same thing.
Finally, I'll say that if you already have working ActiveRecord code that does what you want, it's probably not worth the effort to port the code to Sequel unless you plan on adding features.
Personally, I wouldn't do it. Just managing connection more-or-less by hand would be tedious, for a start. I'd be more inclined, if I felt Sequel was the stronger option, to hold off for Rails 3.0 (or perhaps start developing against Edge Rails) where it should be fairly easy to switch ORMs, if Yehuda and co are doing their stuff right. A lot more Merb-like than now, at least.
This was DHH's take on the subject (I'm not saying it should be taken as gospel truth, mind, but it is, so to speak, from the horse's mouth):
But Isn’t Sql Dirty?
Ever since programmers started to
layer object-oriented systems on top
of relational databases, they’ve
struggled with the question of how
deep to run the abstraction. Some
object-relational mappers seek to
eradicate the use of SQL entirely,
striving for object oriented purity by
forcing all queries through another OO
layer.
Active Record does not. It was built
upon the notion that SQL is neither
dirty nor bad, just verbose in the
trivial cases. The focus is on
removing the need to deal with the
verbosity in those trivial cases but
keeping the expressiveness around for
hard queries – the type SQL was
created to deal with elegantly.
Therefore, you shouldn’t feel guilty
when you use find_by_sql() to handle
either performance bottlenecks or hard
queries. Start out using the
object-oriented interface for
productivity and pleasure, and the dip
beneath the surface for a
close-to-the-metal experience when you
need to.
(Quote was found here, original text is on p334 of AWDRWR, the "hammock" book).
I think that's reasonable.
Are we talking about something that find_by_sql can't handle? Or are we talking about complex non-SELECT stuff that execute can't deal with?
Any examples we could look at?