Giter Site home page Giter Site logo

cyx / ohm-contrib Goto Github PK

View Code? Open in Web Editor NEW

This project forked from sinefunc/ohm-contrib

83.0 10.0 34.0 324 KB

A collection of decoupled drop-in modules for Ohm

Home Page: http://cyx.github.com/ohm-contrib

License: MIT License

Ruby 99.83% Makefile 0.17%

ohm-contrib's Introduction

ohm-contrib

A collection of drop-in modules for Ohm.

Quick Overview

require 'ohm'
require 'ohm/contrib'

class Post < Ohm::Model
  include Ohm::Timestamps
  include Ohm::DataTypes

  attribute :amount, Type::Decimal
  attribute :url
  attribute :poster_email
  attribute :slug
end

post = Post.create

post.created_at.kind_of?(Time)
# => true

post.updated_at.kind_of?(Time)
# => true

It's important to note that created_at and updated_at both store times as a unix timestamp for efficiency.

Ohm::Callbacks

Note: Macro-style callbacks have been removed since version 1.0.x. Please use instance style callbacks.

On the topic of callbacks

Since I initially released ohm-contrib, a lot has changed. Initially, I had a bad habit of putting a lot of stuff in callbacks. Nowadays, I prefer having a workflow object or a service layer which coordinates code not really related to the model, a perfect example of which is photo manipulation.

It's best to keep your models pure, and have domain specific code in a separate object.

class Order < Ohm::Model
  include Ohm::Callbacks

  attribute :status

  def before_create
    self.status = "pending"
  end

  def after_save
    # do something here
  end
end

Ohm::DataTypes

If you don't already know, Ohm 1.0 already supports typecasting out of the box by taking a lambda parameter. An example best explains:

class Product < Ohm::Model
  attribute :price, lambda { |x| x.to_f }
end

What Ohm::DataTypes does is define all of these lambdas for you, so we don't have to manually define how to cast an Integer, Float, Decimal, Time, Date, etc.

DataTypes: Basic example

class Product < Ohm::Model
  include Ohm::DataTypes

  attribute :price, Type::Decimal
  attribute :start_of_sale, Type::Time
  attribute :end_of_sale, Type::Time
  attribute :priority, Type::Integer
  attribute :rating, Type::Float
end

product = Product.create(price: "127.99")
product.price.kind_of?(BigDecimal)
# => true

product = Product.create(start_of_sale: Time.now.rfc2822)
product.start_of_sale.kind_of?(Time)
# => true

product = Product.create(end_of_sale: Time.now.rfc2822)
product.end_of_sale.kind_of?(Time)
# => true

product = Product.create(priority: "100")
product.priority.kind_of?(Integer)
# => true

product = Product.create(rating: "5.5")
product.rating.kind_of?(Float)
# => true

DataTypes: Advanced example

IMPORTANT NOTE: Mutating a Hash and/or Array doesn't work, so you have to re-assign them accordingly.

class Product < Ohm::Model
  include Ohm::DataTypes

  attribute :meta, Type::Hash
  attribute :sizes, Type::Array
end

product = Product.create(meta: { resolution: '1280x768', battery: '8 hours' },
                         sizes: ['XS S M L XL'])

product.meta.kind_of?(Hash)
# => true

product.meta == { resolution: '1280x768', battery: '8 hours' }
# => true

product.sizes.kind_of?(Array)
# => true

product.sizes == ['XS S M L XL']
# => true

Ohm::Scope

Scope allows you to create named filters on Ohm::Set.

class Product < Ohm::Model
  include Ohm::DataTypes
  include Ohm::Scope
  
  attribute :in_stock, Type::Boolean
  index :in_stock
  
  scope :in_stock?, ->() { find(in_stock: true) }
  
  scope do
    def in_stock?
      find(in_stock: true)
    end
  end
end

product = Product.create(in_stock: true)
Product.all.in_stock?.first == product
# => true

Ohm::Slug

class Post < Ohm::Model
  include Ohm::Slug

  attribute :title

  def to_s
    title
  end
end

post = Post.create(title: "Using Ohm contrib 1.0")
post.to_param == "1-using-ohm-contrib-1.0"
# => true

By default, Ohm::Slug tries to load iconv in order to transliterate non-ascii characters. For ruby 2 or later, you will need to gem install iconv to get transliteration.

post = Post.create(:title => "Décor")
post.to_param == "2-decor"

Ohm::Versioned

For cases where you expect people to be editing long pieces of content concurrently (the most obvious example would be a CMS with multiple moderators), then you need to put some kind of versioning in place.

class Article < Ohm::Model
  include Ohm::Versioned

  attribute :title
  attribute :content
end

a1 = Article.create(:title => "Foo Bar", :content => "Lorem ipsum")
a2 = Article[a1.id]

# At this point, a2 will be stale.
a1.update(title: "Foo Bar Baz")

begin
  a2.update(:title => "Bar Baz")
rescue Ohm::VersionConflict => ex
  ex.attributes == { :title => "Bar Baz", :_version => "1", :content => "Lorem ipsum" }
  # => true
end

ohm-contrib's People

Contributors

badboy avatar catwell avatar cyx avatar der-flo avatar frodsan avatar inkel avatar luiscvega avatar lusis avatar nbphuoc avatar slowernet avatar soveran avatar zdraganov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ohm-contrib's Issues

Allowing nil?

I have an attribute:

  attribute :link, Type::Integer

I'm trying to remove the value but it keeps the 0 value :(

> device.update :link => nil
>  device.link
=> 0

Anyway to have a type but to allow nil?

sorting bug ?

I have a class < Ohm::Model mixing in Ohm::Timestamps and Ohm::DataTypes with 'status' as an integer attribute.

I'm trying to find all entities with a status value and sort them by their updated_at timestamps.

Entity.find(:status => 2).sort(:by => :updated_at, :order => "DESC").map &:updated_at

The redis command it generates doesn't work

"sort" "Entity:indices:status:2" "BY" "updated_at" "DESC"

It should be

"sort" "Entity:indices:status:2" "BY" "Entity:*->updated_at" "DESC"

Is this an ohm / ohm-contrib bug ? Or Did I miss something ?

Type::Array does not work

Consider the following:

class MyObject < Base
  include Ohm::DataTypes
  attribute :groups,  Type::Array
end

obj = MyObject.new
groups = Array.new
groups << "one"
groups << "two"
groups << "three"
groups << "four"
groups << "five"
obj.groups = groups
obj.save

This results in an error:

ERR Error running script (call to f_HASH): @user_script:34: user_script:LINE: Bad data format in input.

Similarly, this fails:

groups = ['one', 'two', 'three', 'four', 'five']
obj.groups = groups

and

obj = MyObject.new(
  groups: ['one', 'two', 'three', 'four', 'five']
)

Any idea why that happens?

Ohm::Timestamps - use c_at and u_at

I have used Redis for years but just getting started with Ohm. I like the timestamps in ohm-contrib but using created_at and updated_at uses up more RAM.

In Mongoid there is a Mongoid::Timestamps::Short which creates c_at and u_at saving disk space. But in your Ruby code you can access either by the long alias created_at or by the short name.
http://www.rubydoc.info/github/mongoid/mongoid/Mongoid/Timestamps/Short

Has anyone tried to implement such feature in ohm-contrib?

Ohm::Timestamps now store times as a UNIX Timestamp.

After upgrading from ohm_contrib 0.0.42 to ohm-contrib-1.2, I assume I need to run through all old time stamps to change them to the new format.
Do you happen to have any scripts or description on how to do this in the easiest possible way?

Currently, after upgrading ohm-contrib, but before doing anythign with the old data, when I try to access a model with timestamps, I get the following issue:
irb(main):001:0> Person[4000]
NoMethodError: undefined method `2011-02-25 21:54:06 UTC=' for :Person

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

what happened to Ohm::Model::Wrapper

I'm upgrading from ohm 0.1.0.rc4 and ohm_contrib 0.0.42 to ohm-1.2.0 and ohm-contrib-1.2.

In one method, I have the following call:
Ohm::Model::Wrapper.new(:User) { Object.const_get(:User) }

which causes the following error:
uninitialized constant Ohm::Model::Wrapper (NameError)

There's no mention of Wrapper here: http://cyx.github.com/ohm-contrib/#upgrade
Any idea what's happened to it?

Between Queries for Timestamps

I was wondering whether it is possible to do "between" queries with the Ohm::Timestamps module.

For example, is it possible to do a query like this ActiveRecord query:

 User.where(created_at: @date_start..@date_end)

Right now, I am just grabbing them all, sorting by created_at and iterating over the results using a select:

AnonymousVisitor.find(store_id: store_id).sort_by(:created_at).select do |visitor|
  visitor.created_at >= date_start && visitor.created_at < date_end
end

But I imagine this will be an expensive operation. Is there a good way to do this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.