ruby activerecord how to use alternate updated_at column - ruby

I am trying to use Rails3 with an existing db schema. The timestamp fields updated_at and created_at need to be mapped to created and modified on the db.
Is there a way to tell activerecord to use alternate column names?
Thanks in advance, Chris
EDIT
Could it be done by having this in a file in the model directory:
module ActiveRecord
module Timestamp
def timestamp_attributes_for_update #:nodoc:
[:modified, :updated_on]
end
def timestamp_attributes_for_create #:nodoc:
[:created, :created_on]
end
end
end

I don't think there is a way to do that without overriding timestamp_attributes_for_update in ActiveRecord:: Timestamp.
A simple workaround would be to use a before_update callback in the model.
before_update :set_modified_time
private
def set_modified_time
self.modified = Time.now
end

Related

Make friendly_id scope play nice with subclassed ActiveRecord model

I have a subclassed ActiveRecord model which uses a separate table to store records and friendly_id (4.1.0.beta.1) to generate slugs. Problem is friendly_id is using the parent class's table to check for existing slugs, instead of using the child table. Basically I'd like friendly_id to scope its checks to the right table.
Example:
class Parent
friendly_id :name, :use => :slugged
end
class Child < Parent
self.table_name = 'children'
end
Parent.create(name: 'hello').slug
> 'hello'
Child.create(name: 'hello').slug
> 'hello--2'
I want friendly_id to generate the 'hello' slug for the second create, because there are no records in the children table with that slug. Is there a way to configure or monkey patch the class friendly id uses for its queries?
EDIT: added friendly_id version for future reference
I'm posting my own solution to this problem, just in case someone is having the same problem. I should reiterate that this problem was found on version 4.1.0.beta.1 of the friendly_id gem (which at the time was the most recent version), so this issue may not occur any more.
To solve this problem, I basically configured slug_generator_class to use my own class, so I could monkey patch the culprit method.
In my model:
friendly_id do |config|
config.slug_generator_class = SubclassScopableSlugGenerator
end
In an initializer, I overrode the FriendlyId::SlugGenerator.conflicts method so I could access the sluggable_class var:
# Lets a non-STI subclass of a FriendlyId parent (i.e. a subclass with its
# own dedicated table) have independent slug uniqueness.
class SubclassScopableSlugGenerator < FriendlyId::SlugGenerator
private
def conflicts
# this is the only line we're actually changing
sluggable_class = friendly_id_config.model_class
pkey = sluggable_class.primary_key
value = sluggable.send pkey
base = "#{column} = ? OR #{column} LIKE ?"
# Awful hack for SQLite3, which does not pick up '\' as the escape character without this.
base << "ESCAPE '\\'" if sluggable.connection.adapter_name =~ /sqlite/i
scope = sluggable_class.unscoped.where(base, normalized, wildcard)
scope = scope.where("#{pkey} <> ?", value) unless sluggable.new_record?
length_command = "LENGTH"
length_command = "LEN" if sluggable.connection.adapter_name =~ /sqlserver/i
scope = scope.order("#{length_command}(#{column}) DESC, #{column} DESC")
end
end

Unit Testing updating a mongoid field using rr

I am trying to unit test the following code:
require 'mongoid'
class Seller
include Mongoid::Document
field :updated_at, type: Time
def update_updated_at
updated_at = Time.now
save
end
end
Here is my attempt
describe Seller do
describe 'update_updated_at' do
it 'sets updated_at to Time.now' do
now = Time.new(2013,10,14)
seller = Seller.new
mock(Time).now { now }
mock(seller).updated_at= now
mock(seller).save
seller.update_updated_at
end
end
end
I am getting the following failure
updated_at=(2013-10-14 00:00:00 -0600)
Called 0 times.
Expected 1 times.
Here is the native method which is updates record updated_at attribute to current time
For example
seller = Seller.first
seller.touch # updated_at set to current time
To mock the Time class there is a gem timecop which is super easy to use and dead simple Time, DateTime mocking e.g
it 'sets updated_at to Time.now' do
now = Time.new(2013,10,14)
Timecop.freeze(now) do
seller = Seller.new
seller.save # 2013-10-14
seller.touch # same time 2013-10-14
end
end
There is no need to mock this. Think about what you're doing here: you're setting updated_at and persisting it to the database. It's generally a code smell to stub/mock #save -- you can trust that it's doing what it should, which is persist attributes to the database. So, call the method, reload the record, and then assert that updated_at is set to the current time (as of when you called the method).
Or, just use touch ;)
By the way this test failed because you used updated_at = Time.now; it would have passed if you'd used self.updated_at = Time.now.

I18n::Backend::ActiveRecord with scope

I want to enable users to overwrite custom translations in the locales/YAML-files.
I use the i18n-active_record gem by Sven Fuchs which works great to use translations stored in the database.
The problem: Users should only get their own translations, not those of others.
So I added a user_id column to the translations table. Now I have no idea how to setup a scope for I18n::Backend::ActiveRecord.
My locale.rb (in config/initializers):
require 'i18n/backend/active_record'
I18n.backend = I18n::Backend::ActiveRecord.new
I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Memoize)
I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Flatten)
I18n::Backend::Simple.send(:include, I18n::Backend::Memoize)
I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
I18n.backend = I18n::Backend::Chain.new(I18n.backend, I18n::Backend::Simple.new)
Thanks for any ideas!
try adding this to an initializer file
ie: added to where you initialize the activerecord backend for i18n
config/initializers/i18n_backend.rb
require 'i18n/backend/active_record'
if ActiveRecord::Base.connection.table_exists? 'translations'
require 'i18n/backend/active_record'
I18n.backend = I18n::Backend::Chain.
new(I18n::Backend::ActiveRecord.new, I18n.backend)
end
# OVERRIDING DEFAULT QUERY
module I18n
module Backend
class ActiveRecord
class Translation < ::ActiveRecord::Base
class << self
def locale(locale)
where(:locale => locale.to_s).where(:field => condition)
end
end
end
end
end
end
this should overrides the default locale method in the i18n-active_record gem

Specify column for model attributes in Rails3?

Is it possible to specify the column for an attribute? I have something like:
NAME, COUNTRY
The database is quite large and I have over a thousand columns which are capitalized like this. I want to refer to them as so:
attr_accessible :name, :country
Where :name = column NAME. I'd prefer Model.name rather than Model.NAME. It isn't possible to downcase every column name in the structure file.
Here is an idea to do the way you preferred.
Command to generate migration: (In my example, im applying this on Posts table. Change according to your table name)
rails g migrate RenameColumnsOfPosts
Below is the migration up method. Here taking all the column names and for each one I'm applying rename_column to make it downcase.
class RenameColumnsOfPosts < ActiveRecord::Migration
def up
Post.columns.map(&:name).each do |column_name|
rename_column(:posts, column_name, column_name.downcase)
end
end
def down
#You can do the opposite operation here. Leaving on you
end
end
As i didnt run it personally, it might need some changes. So start with it and let me know if facing any problem.
Please write code inside of model ,
it's just for demostration code,after you get it and update as per logic :
This Code inside of model :
...
attr_accessor :name,:country
before_save :fill_save
..
#assign variable like ...
def fill_save
self.NAME= self.name
self.COUNTRY= self.country
end
....

does a sequel models generator exists?

I'm looking for a ruby class that could generate the sequel model file for Ramaze after reading the definition of the table in a mySQL database.
For example, I would like to type :
ruby mySuperGenerator.rb "mytable"
And the result shold be the file "mytable.rb" in "model" directory, containing :
class Mytable < Sequel::Model(:mytable)
# All plugins I've defined somewhere before lauching the generator
plugin :validation_helpers
plugin :json_serializer
one_to_many :othertable
many_to_one :othertable2
def validate
# Generating this if there are some not null attributes in this table
validates_presence [:fieldthatshoulnotbenull1, :fieldthatshoulnotbenull2]
errors.add(:fieldthatshoulnotbenull1, 'The field fieldthatshoulnotbenull1 should not be null.') if self.fieldthatshoulnotbenull1.nil?
end
def before_create
# All the default values found for each table attributes
self.creation_time ||= Time.now
end
def before_destroy
# referential integrity
self.othertable_dataset.destroy unless self.othertable.nil?
end
end
Does someone knows if such a generator exists ?
Well...
I finally wrote my script.
see https://github.com/Pilooz/sequel_model_generator Have look and fork !

Resources