Does anyone have an idea on how to implement this (http://railscasts.com/episodes/256-i18n-backends) with MongoDB/Mongoid? My question is primarily about the initializer.rb file.
The docs of Mongo-I18n on github suggests the following using its 'MongoI18n::Store.new' method:
collection = Mongo::Connection.new['my_app_related_db'].collection('i18n')
I18n.backend = I18n::Backend::KeyValue.new(MongoI18n::Store.new(collection)
But how to do this if you don't want to use their plugin? Is there something like a Mongo::Store method?
I just did this exact same thing, except that I had trouble installing Mongo-I18n, because it has a dependency on a very old version of MongoDB.
To get around this, I copied the code from here into lib/mongo_i18n.rb.
You were on the right track with your initializer though, if you're using Mongoid - the best way forward is to do this:
require 'mongo_i18n'
collection = Mongoid.database.collection('i18n')
I18n.backend = I18n::Backend::KeyValue.new(MongoI18n::Store.new(collection))
Which tells the I18n backend to use a new collection (called i18n), but in the same database as the rest of your application.
Make sure you delete the Mongo_I18n gem out of your gemfile and run bundle before starting your server again.
You can access your store directly using:
I18n.backend.store
But to make it a little cleaner, I added this method to my I18n library:
# mongo_i18n.rb
def self.store
collection = Mongoid.database.collection('i18n')
MongoI18n::Store.new
end
So that I can access the store directly with:
MongoI18n.store
I did exactly like theTRON said, except that instead of require 'mongo_i18n' I added whole class MongoI18n::Store definition from Mongo_i18n gem directly to mongo initializer. It not such a big deal, because whole MongoI18n::Store is 41 lines long. Look here, why make dependancy from 41 lines gem ?
Related
I have a basic application running with ruby on rails. I use sqlite3 for development and postgres for production. I recently got access to Orchestrate.io and their student tier.
I would like to know how I could possibly use this with my application. I'm not even sure this is possible. My app is really simple (add-edit-delete). But it would be interesting to have a go at using the tools.
Mostly because I cannot find an efficient and free rails db text search.
You can definitely use Orchestrate as the backend for a Rails application.
A few different options:
The Orchestrate-Ruby client has both a method client & object client. Although the object client is still considered a work-in-progress, the method client provides a solid interface for connecting to the Orchestrate API.
Use an http library (such as rest-client or faraday) to make calls to the Orchestrate API.
There's also the Orchestrate-Rails gem. Your mileage may vary with this (last updated in April).
To use Orchestrate as the only backend (no postgres/mysql), I've found the best approach is to disable ActiveRecord:
When creating a new application, you can use -O to skip ActiveRecord:
rails new my_app -O
For existing applications:
1. Remove database adapter gems from your Gemfile (pg, mysql2, sqlite3, etc.)
2. Change your config/application.rb
Remove require 'rails/all line and require frameworks you want to use, for example:
require "action_controller/railtie"
require "action_mailer/railtie"
require "sprockets/railtie"
require "rails/test_unit/railtie"
3. Delete your database.yml file, db/schema.rb and migrations (if any)
4. Delete migration check in test/test_helper.rb
5. Delete any ActiveRecord configuration from your config/environments files (this is what is causing your error)
If you run into problems/errors, stack trace should give you sufficient information on what you need to change. You might for example have some ActiveRecord configuration in your initializers.
With the Orchestrate-Ruby client, you can define a model like so:
class Foo < Orchestrate::Collection
...
end
I'm still undecided on what the best approach for defining the Application object is, but one way I've done it is by making a global object with an initializer:
# /config/initializers/orchestrate.rb
$App = Orchestrate::Application.new(ENV['ORCHESTRATE_KEY']) # using dotenv gem
$App = Orchestrate::Application.new('your_key_here') # without dotenv
From here, you can then access the $App object in your controllers (to initialize the collection object):
class FoosController < ApplicationController
def index
#foos = Foo.new($App, "foos").each
end
end
Leveraging model concerns might be a better way to share the Application object/API key between models. Or you could roll your own classes on top of the method client.
Hope this helps!
I'll be looking into how to accomplish this in a more 'Railsy' way.
EDIT: also, textacular is a ruby gem which provides full-text search and indexing for postgres
how do i access a variable from an initializer file?
i have a file called search.rb in my initializer folder
api_client = IndexTank::Client.new 'http://:xxyyzz#xv9v.api.searchify.com'
index = api_client.indexes 'idx'
however, in my controller whenever im trying to index a newly created lesson, rails gives me an error of
undefined method `document' for nil:NilClass
my controller is...
def create
index.document(#lesson.id).add({:text => #lesson.content })
end
also is this a bad way of indexing my documents? whenever they're being created? thanks
You might find it useful to look at the Tanker gem by kidpollo - https://github.com/kidpollo/tanker
It's a 3rd party IndexTank gem for rails. You don't actually have to use it - you can keep using the indextank gem if you want. But looking at the source of the Tanker gem may be helpful in figuring out the best way to write your code under rails.
Looks like index object was not initialized.
NO, it isn't a bad way for indexing your documents.
But, I suggest to move indexing in special Index model which will handle all indexing logic for the particular index.
Think of index like of database table.
Ok, I have a rails gem that I am working on and I want it to override a specific method in sprockets.
The method I want to override is: Sprockets::Base.digest so that I can base the fingerprint off my gem version when compiling the app's assets.
How would I go about doing that?
In my gem I create a file lib/sprockets/base.rb and place the following code:
class Sprockets::Base
def digest
#digest = digest_class.new.update(MyGem::VERSION)
#digest.dup
end
end
When I run bundle exec rake assets:precompile I get:
undefined method 'logger=' for #<Sprockets::Environment:0x1315b040>
So it almost seems to me like the entire class is getting overridden somehow (this losing that, and the other methods), instead of just overriding the one method.
If I include that snippet of code directly into the app's rakefile that's using both gems, things work perfectly.
It's impossible to override an entire Ruby class in that manner, but I think it is possible to prevent the original class from loading...if it's using autoload. I was curious, so I checked out https://github.com/sstephenson/sprockets/blob/master/lib/sprockets.rb, and yes, Sprockets is using autoload.
autoload :Base, "sprockets/base"
Importantly, that doesn't load the code. It simply tells Ruby that if/when an undefined constant called "Sprockets::Base" is ever encountered, to load it from the specified file. Your patch defines Sprockets::Base before it is ever called anywhere, thus preventing the original file from loading.
When you moved your patch to the Rakefile, something in Rails had already referenced Sprockets::Base, loading the original code. Your patch then applied cleanly on top.
I've never actually used autoload, so I'm not sure how cases like this are supposed to be handled. I'm betting though, that this would work:
Sprockets::Base
class Sprockets::Base
def digest
...
By referencing the class first, you should force Ruby to load the original class. Then you can safely go about the business of overriding one of its methods.
Ok, I marked your answer correct, but it really only led me to figure out the problem.
Anyway, the rails app was requiring my base file instead of the one in the gem itself. Which is what you said. However, the reason it was happening seems to have been caused by the path itself. The path to the file was basically the same as the gem's (lib/sprockets/base.rb).
Moving that file into my gem's "namespace" (lib/my_gem instead of lib/sprockets) and renaming it to sprockets_base.rb fixed the problem! Weird, huh?
In other words, me trying to keep the directory structure nice actually seems to have confused Rails into thinking it was the gem itself or something.
Pretty self explanatory.
I use array_name.first to get the first element. How do you extend it to get second, third, random, etc?
Thanks.
In Ruby you can just reopen any existing class and add your own functions.
In rails, you already have those methods defined in activesupport
See the source at github: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/array/access.rb
I discovered it is already there, in Ruby 1.9.2 at least.
If it weren't there, I would create a file in config/initializers called array_helper.rb (or whatever) and add the following code:
class Array
def second
self[1]
end
end
Why? Because all classes in Ruby are open and you can extend anything you want.
Here's some tricks to know:
When working in the console, if you want to test the file, be sure to use rails console and not irb. Also, do reload! after creating or updating the above file. Finally, all objects must be recreated to use the new code after reload!.
I'm using the Rails gem SimpleForm, but I think my question may be applicable to any gem.
https://github.com/plataformatec/simple_form
It has a lot of great features and customization, but I'm looking to go a bit further. For example, I really wish the markup generated had no default classes inserted into it, but I'd still like the ability to insert my own manually. I found that I could remove some of the classes by commenting out lines in the gem files. However this is outside of my project-- I would want a DRY solution that will stay with my project when I deploy to production, preferably without having to pack all of my gems.
I imagine this is a common situation that could apply to any gem, and I should be able to override any gem wholly or partially probably by adding customs files in my project that override the gem... but I'm not sure how.
Any help would be appreciated! Thanks.
Are you talking about monkey patching? Say your gem has a class in a file
# simple_form_gem/lib/some_file.rb
class A
def some_method
puts 'A'
end
end
If you want to change the output of #some_method then you can create an initializer file and do
# config/initializers/my_monkey_patch_for_simple_form_gem.rb
class A
def some_method
puts 'duck punching'
end
end
Your monkey patch will only affect A#some_method, and not other methods in A. Just make sure the output of your monkey patch won't break something else in the gem.