From 63fb953441e1467c5903d2c8d21bd3812ee2aa69 Mon Sep 17 00:00:00 2001 From: Ed Jones Date: Mon, 1 Dec 2014 01:18:20 +0000 Subject: [PATCH] First commit of contentful_model in its own repo --- .gitignore | 10 +++++ Gemfile | 14 +++++++ Gemfile.lock | 24 ++++++++++++ MIT-LICENSE | 20 ++++++++++ README.md | 43 +++++++++++++++++++++ Rakefile | 32 +++++++++++++++ contentful_model.gemspec | 24 ++++++++++++ lib/contentful_model.rb | 41 ++++++++++++++++++++ lib/contentful_model/base.rb | 45 ++++++++++++++++++++++ lib/contentful_model/chainable_queries.rb | 47 +++++++++++++++++++++++ lib/contentful_model/query.rb | 17 ++++++++ lib/contentful_model/version.rb | 3 ++ lib/tasks/contentful_rails_tasks.rake | 4 ++ 13 files changed, 324 insertions(+) create mode 100644 .gitignore create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 MIT-LICENSE create mode 100644 README.md create mode 100644 Rakefile create mode 100644 contentful_model.gemspec create mode 100644 lib/contentful_model.rb create mode 100644 lib/contentful_model/base.rb create mode 100644 lib/contentful_model/chainable_queries.rb create mode 100644 lib/contentful_model/query.rb create mode 100644 lib/contentful_model/version.rb create mode 100644 lib/tasks/contentful_rails_tasks.rake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..010d7ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.bundle/ +log/*.log +pkg/ +test/dummy/db/*.sqlite3 +test/dummy/db/*.sqlite3-journal +test/dummy/log/*.log +test/dummy/tmp/ +test/dummy/.sass-cache +.idea/* +.idea/.* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..19bb0d3 --- /dev/null +++ b/Gemfile @@ -0,0 +1,14 @@ +source "https://rubygems.org" + +# Declare your gem's dependencies in contentful_rails.gemspec. +# Bundler will treat runtime dependencies like base dependencies, and +# development dependencies will be added by default to the :development group. +gemspec + +# Declare any dependencies that are still in development here instead of in +# your gemspec. These might include edge Rails or gems from your path or +# Git. Remember to move these dependencies to your gemspec before releasing +# your gem to rubygems.org. + +# To use debugger +# gem 'debugger' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..6ab05da --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,24 @@ +PATH + remote: . + specs: + contentful_model (0.0.1) + contentful + redcarpet + +GEM + remote: https://rubygems.org/ + specs: + contentful (0.4.0) + http (~> 0.6) + multi_json (~> 1) + http (0.6.3) + http_parser.rb (~> 0.6.0) + http_parser.rb (0.6.0) + multi_json (1.10.1) + redcarpet (3.2.1) + +PLATFORMS + ruby + +DEPENDENCIES + contentful_model! diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 0000000..ea966ec --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright 2014 YOURNAME + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..74e7574 --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +# ContentfulModel + +This is a thin wrapper around the [Contentful.rb](https://github.com/contentful/contentful.rb) api client library. + +It allows you to inherit from `ContentfulModel::Base` and specify the content type id, and optionally, fields to coerce in a specific way. + +# Usage + +## Configure ContentfulModel + +Configure ContentfulModel with a block. In a Rails app this is best done in an initializer: + +``` +ContentfulModel.configure do |config| + config.access_token = "your access token in here" + config.space = "your space id in here" + config.options = { + #extra options to send to the Contentful::Client + } +end + +``` + +## Create a model class + +Create a class which inherits from `ContentfulModel::Base`. + +``` +class Foo < ContentfulModel::Base + self.content_type = "content type id for this model" +end +``` + +ContentfulModel takes care of setting instance variables for each field in your model. You can optionally coerce fields to the right format - for example dates: + +``` +class Foo < ContentfulModel::Base + self.content_type = content type id for this model" + + coerce_field birthday: :date + coerce_field store_id: :integer +end +``` diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..1578ea9 --- /dev/null +++ b/Rakefile @@ -0,0 +1,32 @@ +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +require 'rdoc/task' + +RDoc::Task.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'ContentfulModel' + rdoc.options << '--line-numbers' + rdoc.rdoc_files.include('README.rdoc') + rdoc.rdoc_files.include('lib/**/*.rb') +end + + + + +Bundler::GemHelper.install_tasks + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + + +task default: :test diff --git a/contentful_model.gemspec b/contentful_model.gemspec new file mode 100644 index 0000000..12eec5e --- /dev/null +++ b/contentful_model.gemspec @@ -0,0 +1,24 @@ +$:.push File.expand_path("../lib", __FILE__) + +# Maintain your gem's version: +require "contentful_model/version" + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |s| + s.name = "contentful_model" + s.version = ContentfulModel::VERSION + s.authors = ["Error Creative Studio"] + s.email = ["hosting@errorstudio.co.uk"] + s.homepage = "http://www.errorstudio.co.uk" + s.summary = "A thin wrapper for Contentful gem" + s.description = "A wrapper around the Contentful gem to give you a base class to inherit your models from" + s.license = "MIT" + + s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"] + s.test_files = Dir["test/**/*"] + + s.add_dependency "contentful" + s.add_dependency "redcarpet" + + #s.add_development_dependency "sqlite3" +end diff --git a/lib/contentful_model.rb b/lib/contentful_model.rb new file mode 100644 index 0000000..08960be --- /dev/null +++ b/lib/contentful_model.rb @@ -0,0 +1,41 @@ +require 'contentful' +require "contentful_model/chainable_queries" +require "contentful_model/base" +require "contentful_model/query" + +module ContentfulModel + class << self + #access the configuration class as ContentfulModel.configuration + attr_accessor :configuration + + #block for configuration. + def configure + self.configuration ||= Configuration.new + yield(configuration) + end + end + + class Configuration + attr_accessor :access_token, :space, :entry_mapping + + def initialize + @entry_mapping ||= {} + end + + #Rather than listing out all the possible attributes as setters, we have a catchall + #called 'options' which takes a hash and generates instance vars + #@param options [Hash] + def options=(options) + options.each do |k,v| + instance_variable_set(:"@#{k}",v) + end + end + + + # Return the Configuration object as a hash, with symbols as keys. + # @return [Hash] + def to_hash + Hash[instance_variables.map { |name| [name.to_s.gsub("@","").to_sym, instance_variable_get(name)] } ] + end + end +end diff --git a/lib/contentful_model/base.rb b/lib/contentful_model/base.rb new file mode 100644 index 0000000..3f772be --- /dev/null +++ b/lib/contentful_model/base.rb @@ -0,0 +1,45 @@ +module ContentfulModel + class Base < Contentful::Entry + include ContentfulModel::ChainableQueries + + def initialize(*args) + super + self.class.coercions ||= {} + fields.each do |k,v| + self.class.send(:attr_accessor, k) + if self.class.coercions[k].nil? + instance_variable_set(:"@#{k}", v) + else + instance_variable_set(:"@#{k}", self.class::COERCIONS[self.class.coercions[k]].call(v)) + end + end + end + + class << self + attr_accessor :content_type_id, :coercions + + def client + unless ContentfulModel.configuration.entry_mapping.has_key?(@content_type_id) + ContentfulModel.configuration.entry_mapping[@content_type_id] = Object.const_get(self.to_s.to_sym) + end + + @@client ||= Contentful::Client.new(ContentfulModel.configuration.to_hash) + end + + def content_type + client.content_type(@content_type_id) + end + + def coerce_field(coercions_hash) + self.coercions = coercions_hash + end + + end + + + + + + + end +end \ No newline at end of file diff --git a/lib/contentful_model/chainable_queries.rb b/lib/contentful_model/chainable_queries.rb new file mode 100644 index 0000000..effe279 --- /dev/null +++ b/lib/contentful_model/chainable_queries.rb @@ -0,0 +1,47 @@ +module ContentfulModel + module ChainableQueries + def self.included(base) + base.extend ClassMethods + base.class_eval do + attr_accessor :query + end + end + + module ClassMethods + def all + raise ArgumentError, "You need to set self.content_type in your model class" if @content_type_id.nil? + @query ||= ContentfulModel::Query.new(self) + self + end + + def first + @query ||= ContentfulModel::Query.new(self) + @query << {'limit' => 1} + self + end + + def offset(n) + @query ||= ContentfulModel::Query.new(self) + @query << {'skip' => n} + self + end + + def search(parameters) + @query ||= ContentfulModel::Query.new(self) + if parameters.is_a?(Hash) + parameters.each do |field, search| + @query << {"fields.#{field}[match]" => search} + end + elsif parameters.is_a?(String) + @query << {"query" => parameters} + end + self + end + + def load + @query.execute + end + end + + end +end \ No newline at end of file diff --git a/lib/contentful_model/query.rb b/lib/contentful_model/query.rb new file mode 100644 index 0000000..2319548 --- /dev/null +++ b/lib/contentful_model/query.rb @@ -0,0 +1,17 @@ +module ContentfulModel + class Query + attr_accessor :parameters + def initialize(reference_class, parameters=nil) + @parameters = parameters || { 'content_type' => reference_class.content_type_id } + @client = reference_class.client + end + + def <<(parameters) + @parameters.merge!(parameters) + end + + def execute + @client.entries(@parameters) + end + end +end \ No newline at end of file diff --git a/lib/contentful_model/version.rb b/lib/contentful_model/version.rb new file mode 100644 index 0000000..39e7b54 --- /dev/null +++ b/lib/contentful_model/version.rb @@ -0,0 +1,3 @@ +module ContentfulModel + VERSION = "0.0.1" +end diff --git a/lib/tasks/contentful_rails_tasks.rake b/lib/tasks/contentful_rails_tasks.rake new file mode 100644 index 0000000..521bcc6 --- /dev/null +++ b/lib/tasks/contentful_rails_tasks.rake @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :contentful_rails do +# # Task goes here +# end