Using ar-extensions' import: synchronise doesn't work - ruby-on-rails

I am using AR-Extensions to import a large number of objects to db, but synching them back from DB just isn't working.
MY code:
posts = [Post.new(:name=>"kuku1"), Post.new(:name=>"kuku2"), ...]
Post.import posts, :synchronize=>posts
posts are submitted to db, and each one is allocated with primary key (id) automatically. But when afterwards checking the objects in posts array, I see that they don't have id field, and new_record flag is still true.
I also tried adding :reload=>true, but that doesn't help as well.
Any idea why synch doesn't work?

This is not possible right now with new records. As of ar-extensions 0.9.3 this will not work when synchronizing new records as synchronizing expects the records you're sync'ing to already exist. It uses the primary key under the covers to determine what to load (but with new records the primary key is nil). This limitation* also exists in activerecord-import 0.2.5. If you can synchronize on other conditions I'd be happy to release a new gem allowing conditions to be passed in. For Rails 3.x you need to use activerecord-import though (it replaces ar-extensions). Please create ticket/issue on github: https://github.com/zdennis/activerecord-import/issues
For Rails 2.x you still want to use ar-extensions, and I'd likely backport the activerecord-import update and push out a new gem as well. If you'd like this functionality here please create a ticket/issue on github: https://github.com/zdennis/ar-extensions/
Patches are welcome as well.
*The limitation here is a database constraint, as its impossible to get the ids of all newly created records after a single insert/import without doing something strange like table locking, which I don't think is a good solution to that problem. If anyone has ideas I'm all ears.
UPDATE
activerecord-import 0.2.6 and ar-extensions 0.9.4 have been released and includes support for specifying the fields you want to synchronize on. Those fields should be unique. See http://www.continuousthinking.com/2011/4/6/activerecord-import-0-2-6-and-ar-extensions-0-9-4

Related

Versioning for Rails i18n translations

I'm in the process of building a volunteer based translation engine for a new site built in Rails 4.0. Since it's volunteer based, there is always the possibility that a user may enter a translation that others do not agree with, accidentally remove a translation, etc. In such an event, I would like to give users the option to revert to a previous translation.
I did some searching around but have yet to find a solution aside from writing my own I18n backend. Is there a simpler way of storing previous versions of translations?
I'm currently using Sven Fuchs' Active Record as a backend, however I'm seriously thinking about switching due to possible performance issues later on down the road.
We had a very successful experience using Globalize (github page: https://github.com/globalize/globalize) and as for the versioning part we didn't try it but Globalize does have support for that in a seperate gem github page: (https://github.com/globalize/globalize-versioning)
After tens of painful gem experiences, i found that comparing gems by last update date and how frequent is new releases, bugs fixes and support is a major factor to decide which one will make your life easier and which one won't.
Update:
You can use Globalize to dynamically translate views (check tutorial) but i came across a github project called iye. I think it suits your needs best (github page: https://github.com/firmafon/iye)
I used Nimir's help to find this solution. Like Globalize Versioning, you can add Paper Trail support for the Active Record's Translation class, however there are a few pitfalls to this method currently.
First you need to include the gems in your Gemfile:
gem "i18n-active_record"
gem "paper_trail"
Then you need to make sure your Translation model class is inheriting from I18n Active Record::Translation and call and calls has_paper_trail:
class Translation < I18n::Backend::ActiveRecord::Translation
has_paper_trail
end
This should really be enough, however the store_translations method in I18n Active Record do not update existing records. Instead, each time a record is added, all records with the given key are deleted and a new record is created. This causes confusion for Paper Trail since it relied on an id.
To get around this issue, I created my own store_translation method, which will update records if they exist:
def store_translations(locale, data, options = {})
escape = options.fetch(:escape, true)
I18n.backend.flatten_translations(locale, data, escape, false).each do |key, value|
t = Translation.find_or_create_by!(locale: locale.to_s, key: key.to_s)
t.value = value
t.save
end
I18n.backend.reload!
end
Notice I also included I18n.backend.reload!, this is because I am running Memoize to cache translations but it seems that it needs to be told to recache whenever a record is updated.
Now I can simply call:
store_translations(lang, {key => key}, :escape => false)
to a store a new translation and ensure we keep a record of the old one and who made the change.

What could be causing a skip in object_ids

After inadvertently overwriting my development database of ~100 rows/table with my fixtures test data (just 2 rows/table), the next new object created in each model started at id = 897600.
What could have caused this? Does this mean I created 897500 test objects that are somehow not visible in my database? Not sure if this is something I should be concerned with, but any feedback would be appreciated.
I'm using PostgreSQL 9.1 with Rails 3.2
Please let me know what additional information would be useful in clarifying my question. Thanks!
Rails fixtures use hashes of fixture keys in order to determine record ids. This allows all the good stuff (some old article from around the time this feature was introduced). In order for your tests to run, records which get created in test examples need not to clash with these hash ids, so ActiveRecord resets PK sequences to max(id)+1 for each table which it touches with fixtures. Here's how your PKs can get up to numbers like 897600.

Mongoid and Postgres Scaffolding/Relationships

I have a need for a certain model to contain a reference to a document. Most of the model could be stored in postgres. The model is for a "level" in a game. I'd like to store the level data itself inside of a document, which makes more sense than making a complex tree in sql.
I am able to use postgres with mongoid installed; however, after installing the mongoid gem I seem to only be able to scaffold mongoid (non active record) documents.
The problem is that I have references to other tables, and I don't neccesarily know how to link that up within a mongoid model.
Questions:
How can I force scaffolding to occur with active record instead of mongoid or vice versa. Edit: partly answered here: Using Active Record generators after Mongoid installation? (2nd answer works, but I don't know how to go back and forth easily)
Is there an easy way to reference a document from an active record model (I know the documentation said don't mix them, but it is ideal for what I am trying to do).
If it is not possible to mix them, then how should I make a document be referenced from a postgres/active record table. In other words how can I get both pieces of data at the same time?
Thanks!
Regarding your first question, the ideal solution would be something along the lines of the first answer in the referenced post. However, instead of a generating a migration, generate a model instead. So when you want an Active Record model simply run:
rails g active_record:model
As for your second and third questions, to associate an Active Record model with a Mongoid document simply store the ObjectId as a string in the model. Then, when you get retrieve a record make a new ObjectId out of the string and use that to query for the related document.
You can create object ids out of the strings like this:
BSON::ObjectId.from_string("object_id_string")
There isn't really an easy way to easily follow intra-orm relations when mixing and matching between ActiveRecord and Mongoid though so I'm afraid that will have to be done via Ruby code.
The models you define in rails either extend one ORM's base class or the other and they don't know about one another. There may be projects out there that act as a layer on top of these ORMs but I am not familiar with any that exist at the moment.

Scaffolding user ID resetting

in the application i am currently creating in ruby on rails. I am trying to do some tests in rails console where i have to destroy data in the database and the database is connected to a server. I am importing an XML and parsing it and putting it into a database with scaffolding.
Now what i need: Basically what i am attempting to do is to destroy the data and replace it with a new one every week..but the problem i am getting, the userid is gone up to 700+ and there are only 50 records :S cause it doesnt reset...
To delete all records i am currently using "whatever.destroy_all" does the trick
Any help?
Btw i am using SQLITE
The ID column created in the table usually is set as unique and to increment by 1 for each new record, which is why each time you destroy and add new data the ID keeps getting higher.
The fact that the ID # is getting larger and larger is not an issue at all.
If you really want to start back at zero, I would think you could drop the table and recreate it, but that seems like overkill for a trivial issue.
Regarding the connection to the other scaffold, how are you connecting the two and what do they both represent?
Ideally the data population for testing should be done through fixtures (or easy tools such as factorygirl etc..)
The main advantage of having a fix data set is you can run your tests in any environment. But as per your requirement you can do something like this,
When you populate the date through the active records pass the id parameter as well
Ex: User.new(:id => 1, :name => "sameera").create
By this way you can have constant id's But make sure you increment the id accordingly.

Understanding Simple ActiveRecord Updates in Rails

I'm just diving into ActiveRecord and have not been able to find an answer to my question. If I am updating an object's attributes and then calling save()... will ActiveRecord save to the DB ONLY when the new values are different from the old values?
Let's say I do something like this:
thing_to_update = Thing.find_or_create_by_code(some_code)
if thing_to_update.name != some_name
thing_to_update.update_attribute(:name, some_name)
end
I don't want to do extra calls to the db if I don't have to because I will potentially have to update a lot of objects. I tried to read through the docs and it doesn't mention anything about comparing new values with the old ones. Am I missing something here?
Thanks
Active Record didn't used to do partial SQL updates, but it has since April 2008.
What's new in Edge Rails: Partial Updates
ActiveRecord::Dirty documentation
ActiveRecord will not update your record if no attributes have changed. You can verify this yourself by calling thing_to_update.save from the console and observing the log. ActiveRecord will load the record, but it will not attempt to update it.

Resources