innate-2013.02.21/0000755000004100000410000000000012166103251013405 5ustar www-datawww-datainnate-2013.02.21/.travis.yml0000644000004100000410000000055112166103251015517 0ustar www-datawww-datascript: 'RUBYOPT=-rubygems rake bacon' before_script: - test -s "$HOME/.rvm/scripts/rvm" && source "$HOME/.rvm/scripts/rvm" - test -s .gems && rvm gemset import .gems rvm: - 1.8.7 - 1.9.2 - 1.9.3 - jruby-18mode - jruby-19mode - rbx-18mode - rbx-19mode - ruby-head notifications: email: - mf@rubyists.com branches: only: - master innate-2013.02.21/tasks/0000755000004100000410000000000012166103251014532 5ustar www-datawww-datainnate-2013.02.21/tasks/authors.rake0000644000004100000410000000201212166103251017056 0ustar www-datawww-data# Once git has a fix for the glibc in handling .mailmap and another fix for # allowing empty mail address to be mapped in .mailmap we won't have to handle # them manually. desc 'Update AUTHORS' task :authors do authors = Hash.new(0) `git shortlog -nse`.scan(/(\d+)\s(.+)\s<(.*)>$/) do |count, name, email| case name when "ahoward" name, email = "Ara T. Howard", "ara.t.howard@gmail.com" when "Martin Hilbig blueonyx@dev-area.net" name, email = "Martin Hilbig", "blueonyx@dev-area.net" when "Michael Fellinger m.fellinger@gmail.com" name, email = "Michael Fellinger", "m.fellinger@gmail.com" end authors[[name, email]] += count.to_i end File.open('AUTHORS', 'w+') do |io| io.puts "Following persons have contributed to #{GEMSPEC.name}." io.puts '(Sorted by number of submitted patches, then alphabetically)' io.puts '' authors.sort_by{|(n,e),c| [-c, n.downcase] }.each do |(name, email), count| io.puts("%6d %s <%s>" % [count, name, email]) end end end innate-2013.02.21/tasks/changelog.rake0000644000004100000410000000113512166103251017325 0ustar www-datawww-datadesc 'update changelog' task :changelog do File.open('CHANGELOG', 'w+') do |changelog| `git log -z --abbrev-commit`.split("\0").each do |commit| next if commit =~ /^Merge: \d*/ ref, author, time, _, title, _, message = commit.split("\n", 7) ref = ref[/commit ([0-9a-f]+)/, 1] author = author[/Author: (.*)/, 1].strip time = Time.parse(time[/Date: (.*)/, 1]).utc title.strip! changelog.puts "[#{ref} | #{time}] #{author}" changelog.puts '', " * #{title}" changelog.puts '', message.rstrip if message changelog.puts end end end innate-2013.02.21/tasks/setup.rake0000644000004100000410000000042712166103251016541 0ustar www-datawww-datadesc 'install dependencies from gemspec' task :setup => [:gem_setup] do GemSetup.new :verbose => false do DEPENDENCIES.each do |name, options| gem(name, options) end DEVELOPMENT_DEPENDENCIES.each do |name, options| gem(name, options) end end end innate-2013.02.21/tasks/manifest.rake0000644000004100000410000000015212166103251017202 0ustar www-datawww-datadesc 'update manifest' task :manifest do File.open('MANIFEST', 'w+'){|io| io.puts(*GEMSPEC.files) } end innate-2013.02.21/tasks/rcov.rake0000644000004100000410000000106712166103251016353 0ustar www-datawww-datadesc 'code coverage' task :rcov => :clean do specs = Dir['spec/innate/**/*.rb'] specs -= Dir['spec/innate/cache/common.rb'] # we ignore adapter as this has extensive specs in rack already. ignore = %w[ gem rack bacon innate/adapter\.rb ] ignore << 'fiber\.rb' if RUBY_VERSION < '1.9' ignored = ignore.join(',') cmd = "rcov --aggregate coverage.data --sort coverage -t --%s -x '#{ignored}' %s" while spec = specs.shift puts '', "Gather coverage for #{spec} ..." html = specs.empty? ? 'html' : 'no-html' sh(cmd % [html, spec]) end end innate-2013.02.21/tasks/reversion.rake0000644000004100000410000000035212166103251017412 0ustar www-datawww-datadesc "update version.rb" task :reversion do File.open("lib/#{GEMSPEC.name}/version.rb", 'w+') do |file| file.puts("module #{PROJECT_MODULE}") file.puts(' VERSION = %p' % GEMSPEC.version.to_s) file.puts('end') end end innate-2013.02.21/tasks/gem_setup.rake0000644000004100000410000000500112166103251017362 0ustar www-datawww-datatask :gem_setup do class GemSetup def initialize(options = {}, &block) @gems = [] @options = options.dup @verbose = @options.delete(:verbose) run(&block) end def run(&block) return unless block_given? instance_eval(&block) setup end def gem(name, version = nil, options = {}) if version.respond_to?(:merge!) options = version else options[:version] = version end @gems << [name, options] end # all gems defined, let's try to load/install them def setup require 'rubygems' require 'rubygems/dependency_installer' @gems.each do |name, options| setup_gem(name, options) end end def setup_gemspec(gemspec) gemspec.dependencies.each do |dependency| dependency.version_requirements.as_list.each do |version| gem(dependency.name, version) end end setup end # First try to activate. # If activation fails, try to install and activate again. # If the second activation also fails, try to require as it may just as # well be in $LOAD_PATH. def setup_gem(name, options) version = [options[:version]].compact lib_name = options[:lib] || name log "activating #{name}" Gem.activate(name, *version) rescue Gem::LoadError log "activating #{name} failed, try to install" install_gem(name, version, options) end # tell rubygems to install a gem def install_gem(name, version, options) installer = Gem::DependencyInstaller.new(options) temp_argv(options[:extconf]) do log "installing #{name}" installer.install(name, *version) end Gem.activate(name, *version) log "install and final activation successful" rescue Gem::GemNotFoundException => ex log "installation failed: #{ex}, use normal require" require(options[:lib] || name) log "require successful, cannot verify version though" end # prepare ARGV for rubygems installer def temp_argv(extconf) if extconf ||= @options[:extconf] old_argv = ARGV.clone ARGV.replace(extconf.split(' ')) end yield ensure ARGV.replace(old_argv) if extconf end private def log(msg) return unless @verbose if defined?(Log) Log.info(msg) else puts(msg) end end def rubyforge; 'http://gems.rubyforge.org/' end def github; 'http://gems.github.com/' end end end innate-2013.02.21/tasks/ycov.rake0000644000004100000410000000452312166103251016362 0ustar www-datawww-databegin require 'yard' task 'Show Documentation coverage' task :ycov => ['.yardoc'] do YARD::Registry.load_yardoc code_objects = YARD::Registry.paths.map{|path| YARD::Registry.at(path) } code_objects.delete_if{|obj| obj.type == :root } without_doc, with_doc = code_objects.partition{|obj| obj.docstring.empty? } documented = with_doc.size undocumented = without_doc.size total = documented + undocumented percentage = (documented / 0.01) / total puts "Documentation coverage is %d/%d (%3.1f%%)" % [documented, total, percentage] end task 'ycov-full' => ['.yardoc'] do require 'builder' YARD::Registry.load_yardoc code_objects = YARD::Registry.paths.map{|path| YARD::Registry.at(path) } code_objects.delete_if{|obj| obj.type == :root } without_doc, with_doc = code_objects.partition{|obj| obj.docstring.empty? } list_objects = lambda{|body, list| body.table(:width => '100%') do |table| list.group_by{|obj| obj.type }. sort_by{|k,v| k.to_s }.each do |type, objects| table.tr do |tr| tr.th(type.to_s, :colspan => 2) end objects.sort_by{|obj| obj.path }.each do |obj| table.tr do |tr| tr.td obj.path tr.td "#{obj.file} +#{obj.line}" end end end end } File.open('ycov.html', 'w+') do |ycov| builder = Builder::XmlMarkup.new(:target => ycov, :indent=>2) builder.html do |html| html.head do |head| head.title 'YARD Coverage report' end html.body do |body| body.h1 'YARD Coverage report' body.h2 "#{without_doc.size} Undocumented objects" list_objects[body, without_doc] body.h2 "#{with_doc.size} Documented objects" list_objects[body, with_doc] end end end end file '.yardoc' => FileList['lib/**/*.rb'] do files = ['lib/**/*.rb'] options = ['--no-output', '--private'] YARD::CLI::Yardoc.run(*(options + files)) end desc 'Generate YARD documentation' task :yardoc => ['.yardoc'] do files = ['lib/**/*.rb'] options = [ '--output-dir', 'ydoc', '--readme', PROJECT_README, '--db', '.yardoc', '--private'] YARD::CLI::Yardoc.run(*(options + files)) end rescue LoadError # you'll survive end innate-2013.02.21/tasks/grancher.rake0000644000004100000410000000033212166103251017165 0ustar www-datawww-databegin require 'grancher/task' Grancher::Task.new do |g| g.branch = 'gh-pages' g.push_to = 'origin' g.message = 'Updated website' g.directory 'ydoc', 'doc' end rescue LoadError # oh well :) end innate-2013.02.21/tasks/release.rake0000644000004100000410000000221112166103251017012 0ustar www-datawww-datanamespace :release do task :prepare => [:reversion, :authors, :gemspec] task :all => ['release:github', 'release:gemcutter'] desc 'Release on github' task :github => :prepare do name, version = GEMSPEC.name, GEMSPEC.version sh('git', 'add', 'MANIFEST', 'CHANGELOG', 'AUTHORS', "#{name}.gemspec", "lib/#{name}/version.rb") puts <<-INSTRUCTIONS ================================================================================ I added the relevant files, you can commit them, tag the commit, and push: git commit -m 'Version #{version}' git tag -a -m '#{version}' '#{version}' git push ================================================================================ INSTRUCTIONS end desc 'Release on gemcutter' task :gemcutter => ['release:prepare', :package] do name, version = GEMSPEC.name, GEMSPEC.version puts <<-INSTRUCTIONS ================================================================================ To publish to gemcutter do following: gem push pkg/#{name}-#{version}.gem ================================================================================ INSTRUCTIONS end end innate-2013.02.21/tasks/bacon.rake0000644000004100000410000000346112166103251016464 0ustar www-datawww-datarequire 'fileutils' desc 'Run all bacon specs with pretty output' task :bacon do require 'open3' require 'scanf' require 'matrix' specs = PROJECT_SPECS some_failed = false specs_size = specs.size len = specs.map{|s| s.size }.sort.last total_tests = total_assertions = total_failures = total_errors = 0 totals = Vector[0, 0, 0, 0] red, yellow, green = "\e[31m%s\e[0m", "\e[33m%s\e[0m", "\e[32m%s\e[0m" left_format = "%4d/%d: %-#{len + 11}s" spec_format = "%d specifications (%d requirements), %d failures, %d errors" specs.each_with_index do |spec, idx| print(left_format % [idx + 1, specs_size, spec]) Open3.popen3(FileUtils::RUBY, '-w', spec) do |sin, sout, serr| out = sout.read.strip err = serr.read.strip # this is conventional, see spec/innate/state/fiber.rb for usage if out =~ /^Bacon::Error: (needed .*)/ puts(yellow % ("%6s %s" % ['', $1])) else total = nil out.each_line do |line| scanned = line.scanf(spec_format) next unless scanned.size == 4 total = Vector[*scanned] break end if total totals += total tests, assertions, failures, errors = total_array = total.to_a if tests > 0 && failures + errors == 0 puts((green % "%6d passed") % tests) else some_failed = true puts(red % " failed") puts out unless out.empty? puts err unless err.empty? end else some_failed = true puts(red % " failed") puts out unless out.empty? puts err unless err.empty? end end end end total_color = some_failed ? red : green puts(total_color % (spec_format % totals.to_a)) exit 1 if some_failed end innate-2013.02.21/tasks/gem.rake0000644000004100000410000000076212166103251016153 0ustar www-datawww-datatask :gemspec => [:manifest, :changelog] do gemspec_file = "#{GEMSPEC.name}.gemspec" File.open(gemspec_file, 'w+'){|gs| gs.puts(GEMSPEC.to_ruby) } end desc "package and install from gemspec" task :install => [:gemspec] do sh "gem build #{GEMSPEC.name}.gemspec" sh "gem install #{GEMSPEC.name}-#{GEMSPEC.version}.gem" end desc "uninstall the gem" task :uninstall => [:clean] do sh %{gem uninstall -x #{GEMSPEC.name}} end Gem::PackageTask.new(GEMSPEC) do |pkg| pkg.need_tar = true end innate-2013.02.21/README.md0000644000004100000410000004252312166103251014672 0ustar www-datawww-data# Innate Innate is the core of Ramaze, but useful on its own. ## Philosophy The philosophy behind Innate is to provide a simple web framework that: * Stays below 2000 easily readable lines of code * Has Rack as the only dependency * Provides the default helpers * Is easy to encapsulate and reuse in other contexts as a simple rack app * Has a rock-solid and fast implementation * Scores at least 95% in rcov * Is fully documented using YARD ## Innate vs. Ramaze Numerous people asked where Innate fits into the picture of Ramaze and when it would be appropriate to use Innate alone. The answer to this is not as simple as I thought, given that Ramaze improves on it a lot by taking full advantage of the encapsulation. Innate started out as I grew increasingly annoyed by the many hacks and add-ons that diluted the original simplicity of Ramaze as we discovered ways to do things better, so I went on to create something that is impossible to dilute and simply works as a multiplier. It does work standalone, and it might be suitable for applications that just need the little extra over plain old Rack, making it easy to deploy and rely on the stability that comes with simple code. It's also the starting point if you want to study the inner workings of Ramaze without being distracted, all you need to keep in mind is Rack. If all you need is a couple of ERB templates and a few nodes then Innate is the way to go. Upgrading to Ramaze later is quite easy, just change a couple of lines and the power of your code multiplies (again). The split between Innate and Ramaze is clear cut and gives Ramaze freedom to expand in any direction (and I have quite some ideas where to take it). Ramaze adds things that require other dependencies, caching with memcached or sequel, logging with analogger or growl, templating with haml or erubis, just to name a few. Ramaze also adds Apps to the mix, and it is easier to understand them when the concepts of what's going on inside an App are completely abstracted by Innate. To summarize, Innate really keeps it simple, acts as a learning tool and encourages everybody to build on top of it whatever they want. ## Features * Powerful Helper system * Nodes[1] simply include Innate::Node, so class inheritance is your choice. * The only hard dependency is Rack * Easy to get started * Compatible with major Ruby implementations[2]. * Usage of Fiber[3] instead of Thread if possible. * Namespaced serializable configuration system * Simple testing without need of a running server * No clutter in your application directory structure, scales from a single file upwards * Seamless integration with Rack middleware * No patching of ruby core or stdlib. * Direct access to the current Request, Response, and Session from anywhere via Trinity * Works out of the box with ERB the templating engine. * Support for all rack-compatible web-servers. * Dynamic content-representation. [1]: What you may think of as Controller. [2]: This includes: Ruby 1.8, Ruby 1.9.1, JRuby, Rubinius [3]: Fiber is available on 1.9 only at this point. ## Usage A simple example of using Innate that also shows you how to add your custom middleware, write specs and the overall concept: require 'innate' Innate.setup_middleware Innate.map('/') do |env| Rack::Response.new(['Hello, World!']).finish end Innate::Mock.get('/') And another example, using Node with a normal server: require 'innate' class Hi include Innate::Node map '/' def index "Hello, World!" end end Innate.start :adapter => :mongrel ## Installation ### Via git (recommended) Installing Innate from git is highly recommended, since it gives you easy access to alternate branches, bugfixes, and new features. git clone git://github.com/Ramaze/innate.git Do not forget to add the innate/lib directory to your `RUBYLIB` environment variable. For unixish systems you may want to add it to `~/.bashrc` or the equivalent for your shell: export RUBYLIB="~/path/to/innate/lib:$RUBYLIB" ### Via gem install gem install innate ### Direct download Download the latest tarball from [here](http://github.com/Ramaze/innate/tarball/master). ## Concepts First let's see about the good old MVC: ### Model Innate doesn't have any ties to models, it does not offer helpers or rake tasks or whatever you may be expecting, there is no M, use whatever you like. Innate is, however, known to be compatible with the ORMs listed below: * ActiveRecord * DataMapper * M4DBI * Og * Sequel Please consider giving us a heads up about what worked for you if it isn't in the list yet. ### View Innate supports multiple templating engines and it is very easy to add your own. At the moment we offer following engines out of the box: * ERB * Etanni ### Controller Innate follows a different approach than most frameworks, making the controller subclassing obsolete. To make an object accessible from the outside simply include Innate::Node and map it to the location you would like to serve. ## Differences from Ramaze Innate throws a lot overboard; it doesn't provide all the bells and whistles that you may be used to. This makes Ramaze the way to go for larger applications. For this reason, Innate is not only a standalone framework, it is also the core of Ramaze. Ramaze started out without any of the benefits that Rack gives us these days, especially regarding the server handlers, request/response, and middleware. Still it tried to provide everything one might need with the least effort, leading to a lot dependencies (we had things like bacon, simple_http, gettext, mime types, ...) ### Configuration Innate provides the Innate::Options DSL, similar in some aspects to the old Ramaze::Global, but a lot more flexible. Options has namespaces, inheritance, defaults, triggers, documentation, and a sane name. The definition syntax roughly resembles Ramaze::Global. We break with the tradition where all options one would ever need were provided in one file. It made maintenance rather difficult and the code hard to follow. So the new approach is to put options where they belong, alongside the class or module they are used in. There are some things still in Innate.options, but they have large impact on the whole system. Options doesn't do things like merging env variables or parsing ARGV, these are things that Ramaze adds. What makes Options especially useful is that you can use it in your own application to configure it without using diverse routes like putting config into counter-intuitive yaml files, using global variables, or relying on yet another dependency. A small example: module Blog include Innate::Optioned options.dsl do o "Title of the blog", :title, "My Blog" o "Syntax highlighting engine for blog posts", :syntax, :coderay end class Articles Innate.node '/' def index "Welcome to #{Blog.options.title}" end end end ### Controller Away with controllers, long live the Node. Nodes are objects that include Innate::Node and are then considered rack applications that get automatically hooked into the routing. Since every existing Ramaze application relies on Ramaze::Controller and normal subclassing is not without merits as well we keep that part entirely in Ramaze, Controller simply includes Innate::Node and makes it suitable for the usage within Apps. #### Layouts Since layouts were an afterthought in Ramaze, they were made normal actions like every other on the respective controllers, leading to lots of confusion over the correct way to use layouts, the Controller::layout syntax in respect to the real location of layouts, how to exclude/include single actions, where layouts should be stored, how to prevent lookup from external requests, ... I made layouts just as important as views and methods for the Action in Innate, and they have their own root directory to live in and will not be considered as a normal view template, so they cannot be accidentally be rendered as their own actions. This strikes me as important, because I consider layouts to be superior to Ezamar elements and equal to render_partial or render_template, just about every application uses them, so they should be handled in the best way possible. The root directory for layouts is in line with the other default locations: proto |-- layout |-- model |-- node |-- public `-- view While none of these directories is necessary, they are the default locations and should be included in a new proto for Ramaze (except that ramaze uses `/controller` instead of `/node`. Innate will not have project generating capabilities, so we just have to document it very well and provide some example apps. #### Provides This is a major new feature stolen from Merb and adapted for the ease of use of Innate/Ramaze. It won't have all the capabilities one might be used to out of the box, but extending them is easy. Having "provides" means that every Action has different ways of being rendered, depending on so-called wishes, that's what people usually call content-representation. A wish may be anything related to the request object, and by default it will trigger on the filename extension asked for. This enables you to create a single action that can be rendered in json/rss/atom/yaml/xml/xhtml/html/wap or different languages... The dispatching in Node depends on the filename extension by default, but more decision paths can be added to Action by overriding some defaults. Layouts map to wishes just like views, so every content representation can have a suitable layout as well. This is very alien to old Ramaze, which always has a 1:1 mapping between actions and their views and how they are rendered, which made people wonder how to serve sass as css or how to respond with json for a AJAX request until they finally were pointed to setting content-type, using respond and setting up custom routes. I hope this feature makes things simpler for people who care about it while it can be ignored by people who don't. ### More specifics Here I try to list the most important things that Ramaze will offer but that are not included in Innate itself in terms of globs: * cache.rb and cache/*.rb * current/response.rb * tool/{create,mime,localize,daemonize,record,project_creator}.rb * spec/helper/*.rb * snippets/**/*.rb * gestalt.rb * store/default.rb * contrib.rb or any contribs * adapter/*.rb (superseded by a lightweight adapter.rb) * template/ezamar*/* * bacon.rb * dispatcher.rb * dispatcher/*.rb There might be a couple of things I've forgotten, but that's what a quick glance tells me. Let's go through them one by one and consider what's gonna happen to them: ### Cache Caching is a very important concern and one of the most difficult things to get right for any web application. Innate defines the caching API that enables everybody to add caches with very little code. Innate provides caching by the following means: * DRb * Hash * Marshal * YAML Ramaze adds: * Memcached * Sequel And as time goes on there will be many more. ### Response Very little code, it just provides some options regarding default headers and easy ways to reset the response. Ramaze adds some more convenient methods. ### Tools Innate doesn't provide any of the stuff in ramaze/tool and it was removed from Ramaze as well, some of the reasoning is below. #### Tool::Create This has been used by `bin/ramaze --create`, bougyman is working on a new `bin/ramaze` which won't use it, so we removed it. #### Tool::ProjectCreator Dependency for Tool::Create, removed as well. ##### Tool::Daemonize Nothing but issues with this one although it is just a very thin wrapper for the daemons gem. Nobody has contributed to this so far despite the issues and it seems that there are a lot of different solutions for this problem. This was removed from Ramaze and Innate. You may use the daemonize functionality from rackup. ##### Ramaze::Record Well, this might be the most obvious candidate for removal, maybe it can be revived as middleware. The functionality itself was in the adapter and even that's only a few lines. But so far I have never seen any usage of it. ##### Tool::Localize Despite being quite popular it has many issues and is totally unusable if you don't have full knowledge about what is going to be served. I and a lot of other people have used this over time and it has proven itself to be a very easy and straightforward way of doing localization. It think it is better suited as middleware which can be included into rack-contrib and doesn't rely on the normal session but a simple unobfuscated cookie. Innate does not attempt to do anything related to localization. Ramaze builds localization on top of Helper::Localize which does a much better job. ##### Tool::MIME This one was removed, Rack::Mime is the way to go. ### Spec helpers Over the years, Ramaze has collected a wide variety of spec helpers that are not really compatible with each other and rely on real request/response with a running server. Innate provides a better alternative via Innate::Mock for specs, the output formatting is done in a rake task. There is some work in progress to integrate Innate and Ramaze with the rack-test library which will allow us to run specs with webrat (which is able to run using selenium and possibly watir in a DRY way). Rack-test will provide us also with xpath checks, multipart requests, digest authorization, etc. ### Snippets Innate abandons the snippets, keeping your core clean. Ramaze has still a lot of these snippets and will continue to, although I will constantly strive to reduce them slowly. ### Gestalt Gestalt has been the first "templating engine" for Ramaze and is still used in some fractions of the code and various applications. There are a lot of other html/xml builders out there these days so I think this is no good choice for inclusion into Innate. I will keep it inside Ramaze. ### Ramaze::Store::Default This has been removed from Innate and Ramaze. It started out as a simple wrapper for YAML::Store to make the tutorial easier, but I think it gives a wrong impression of being anything else. It's very slow, might raise exceptions under heavy load and a plain YAML::Store or PStore or any other persistence mechanism is generally a better choice, so there is no need to keep this around. ### Contrib Ramaze has some things in contrib, some of them used widely, others not at all. I'm still going through these, putting what is suitable for a wider audience into rack-contrib, including what fits into the Ramaze concept into Ramaze, but none of these will find its way into Innate. One exception, the file cache has been added to Innate already and the sequel cache is in Ramaze proper. The gzip filter has a more powerful and better maintained equivalent in Rack::Deflater. The profiling hook is obsolete as well, there is an equivalent in rack-contrib. The emailer is really light-weight and but lacks support for many things you will need, I'm working on a new Helper::Email that integrates with Mailit (a fork of MailFactory). Things I'll not touch for now are `facebook` and `gettext`. The sequel related stuff will have to be removed and might find a place somewhere else, (somebody start a sequel-contrib already!). The `gems` was refactored and put into `ramaze/setup.rb`, where it provides you with painless first-start experience. ### Adapters These are entirely the responsibility of Rack/Innate now, Ramaze doesn't need to worry about that. WEBrick will remain the default adapter since it is in the Ruby stdlib. ### Templating The basic functionality for templating is provided by Innate, it only provides the `None`, `Etanni` and `ERB` templating engines. The other engines are in Ramaze. #### Ezamar `Ezamar` has become a standalone project. It has been stable since a long time and is suitable for other uses. The battle for the place of the default templating engine in Ramaze is still going on, competitors are `ERB`, `Ezamar`, and `Nagoro`. ### Bacon Bacon is still a dependency for specs, but we don't ship it anymore, the stable release includes all features we need. ### Dispatcher Innate uses a stripped down version of the Ramaze dispatcher. The Ramaze dispatcher was strongly influenced by Nitro, but proved to be a difficult part. We are now using Rack's URLMap directly, and have a minimal dispatching mechanism directly in Node (like we used to have one in Controller). A lot of the functionality that used to be in the different dispatchers is now provided by Rack middleware. The Dispatcher itself isn't needed anymore. It used to setup Request/Response/Session, which was superseded by Current, this again is now superseded by STATE::wrap. We are going to remove all the other dispatchers as well, providing default ways to provide the same functionality, and various middleware to use. #### Dispatcher::Action This dispatcher was used to initiate the controller dispatching, this is now not needed anymore. #### Dispatcher::Directory This will also be removed. There is a directory listing middleware already. #### Dispatcher::Error There's middleware for this as well, and a canonical way of routing errors to other actions. This used to be one of the most difficult parts of Ramaze and it was removed to make things simpler. #### Dispatcher::File This is a combination of the `ETag` and `ConditionalGet` middlewares, ergo Innate and Ramaze will not serve static files themselves anymore, but leave the job to Rack or external servers. innate-2013.02.21/example/0000755000004100000410000000000012166103251015040 5ustar www-datawww-datainnate-2013.02.21/example/session.rb0000644000004100000410000000103712166103251017051 0ustar www-datawww-datarequire 'innate' class Hello Innate.node '/' TEMPLATE = ' Session example

Session example

Value is: #{ session[:value] }
#{ a :increment }
#{ a :decrement }

'.strip def index session[:value] = 0 TEMPLATE end def increment session[:value] = session[:value].to_i + 1 TEMPLATE end def decrement session[:value] = session[:value].to_i - 1 TEMPLATE end end Innate.start innate-2013.02.21/example/app/0000755000004100000410000000000012166103251015620 5ustar www-datawww-datainnate-2013.02.21/example/app/todo/0000755000004100000410000000000012166103251016565 5ustar www-datawww-datainnate-2013.02.21/example/app/todo/spec/0000755000004100000410000000000012166103251017517 5ustar www-datawww-datainnate-2013.02.21/example/app/todo/spec/todo.rb0000644000004100000410000000351712166103251021017 0ustar www-datawww-datarequire 'innate/spec' FileUtils.rm_f('todo.pstore') require 'start' require 'hpricot' describe Todo do behaves_like :mock, :multipart it 'starts out without tasks' do doc = Hpricot(get('/').body) doc.at(:table).inner_text.strip.should.be.empty end it 'adds a task and redirects back' do got = post('/create', multipart('title' => 'first task')) got.status.should == 302 got['Location'].should == 'http://example.org/' end it 'shows the task as pending' do doc = Hpricot(get('/').body) doc.at('td/input[@name=title]')['value'].should == 'first task' doc.at('td/input[@name=done]')['checked'].should.be.nil end it 'updates the task title and redirects back' do got = post('/update', multipart('id' => 'first task', 'title' => 'wash dishes')) got.status.should == 302 got['Location'].should == 'http://example.org/' end it 'shows the changed task title' do doc = Hpricot(get('/').body) doc.at('td/input[@name=title]')['value'].should == 'wash dishes' doc.at('td/input[@name=done]')['checked'].should.be.nil end it 'marks the task as done and redirects back' do mp = multipart('id' => 'wash dishes', 'title' => 'wash dishes', 'done' => 'on') got = post('/update', mp) got.status.should == 302 got['Location'].should == 'http://example.org/' end it 'shows the task as done' do doc = Hpricot(get('/').body) doc.at('td/input[@name=title]')['value'].should == 'wash dishes' doc.at('td/input[@name=done]')['checked'].should == 'checked' end it 'deletes the task and redirects back' do got = post('/delete', multipart('id' => 'wash dishes')) got.status.should == 302 got['Location'].should == 'http://example.org/' end it 'shows no tasks' do doc = Hpricot(get('/').body) doc.at(:table).inner_text.strip.should.be.empty end end innate-2013.02.21/example/app/todo/start.rb0000644000004100000410000000166312166103251020255 0ustar www-datawww-datarequire 'rubygems' require 'innate' require 'pstore' LIST = PStore.new('todo.pstore') class Todo Innate.node '/' layout 'default' def index @list = sync{|list| list.roots.map{|key| [key, list[key]] }} end def create redirect_referer unless request.post? and title = request[:title] title.strip! sync{ LIST[title] = false } unless title.empty? redirect_referer end def update id, title, done = request[:id, :title, :done] redirect_referer unless request.post? and id and title done = !!done title.strip! if id == title sync{ LIST[id] = done } elsif title != '' sync{ LIST.delete(id); LIST[title] = done } end redirect_referer end def delete redirect_referer unless request.post? and id = request[:id] sync{ LIST.delete(id) } redirect_referer end private def sync Innate.sync{ LIST.transaction{ yield(LIST) }} end end Innate.start innate-2013.02.21/example/app/todo/view/0000755000004100000410000000000012166103251017537 5ustar www-datawww-datainnate-2013.02.21/example/app/todo/view/index.xhtml0000644000004100000410000000204512166103251021725 0ustar www-datawww-data
Create new task
innate-2013.02.21/example/app/todo/layout/0000755000004100000410000000000012166103251020102 5ustar www-datawww-datainnate-2013.02.21/example/app/todo/layout/default.xhtml0000644000004100000410000000047512166103251022612 0ustar www-datawww-data Innate TodoList

Organize your life and learn Innate

#{ @content } innate-2013.02.21/example/app/retro_games.rb0000644000004100000410000000225512166103251020460 0ustar www-datawww-datarequire 'innate' require 'yaml/store' STORE = YAML::Store.new('games.yaml') def STORE.[](key) transaction{|s| super } end def STORE.[]=(key, value) transaction{|s| super } end def STORE.each(&block) YAML.load_file('games.yaml').sort_by{|k,v| -v }.each(&block) end STORE['Pacman'] = 1 class Games Innate.node('/') def index TEMPLATE end def create STORE[request[:name]] ||= 0 if request.post? redirect_referrer end def vote(name) STORE[name] += 1 redirect_referrer end TEMPLATE = <<-'T'.strip Top Retro Games

Vote on your favorite Retro Game

  1. #{ a("Vote", r(:vote, u(name))) } #{ h "%5d => %s" % [votes, name] }
T end Innate.start innate-2013.02.21/example/app/whywiki_erb/0000755000004100000410000000000012166103251020143 5ustar www-datawww-datainnate-2013.02.21/example/app/whywiki_erb/spec/0000755000004100000410000000000012166103251021075 5ustar www-datawww-datainnate-2013.02.21/example/app/whywiki_erb/spec/wiki.rb0000644000004100000410000000055312166103251022370 0ustar www-datawww-datarequire 'innate' require 'innate/spec' require 'yaml/store' base = File.join(File.dirname(__FILE__), '..') DB = YAML::Store.new(db_file = "#{base}/spec/wiki.yaml") require "start" Innate.config.app.root = base describe 'Wiki' do it 'should have index page' do page = Innate::Mock.get('/') page.body.should == '' end FileUtils.rm_f(db_file) end innate-2013.02.21/example/app/whywiki_erb/start.rb0000644000004100000410000000143612166103251021631 0ustar www-datawww-data# The minimal _why wiki in Innate with ERB %w[rubygems innate erb maruku yaml/store].each{|l| require(l) } DB = YAML::Store.new('wiki.yaml') unless defined?(DB) class Wiki Innate.node '/' layout 'wiki' provide :html, :engine => :ERB def index(page = 'Home') @page = page @text = 'foo' sync{ @text = DB[page].to_s.dup @text.gsub!(/\[\[(.*?)\]\]/) do %(#{h($1)}) end } end def edit(page) @page = page @text = sync{ DB[page].to_s } end def save page, text = request[:page, :text] sync{ DB[page] = text } if request.post? and page and text redirect(r(page)) end private def sync Innate.sync{ DB.transaction{ yield }} end end Innate.start innate-2013.02.21/example/app/whywiki_erb/view/0000755000004100000410000000000012166103251021115 5ustar www-datawww-datainnate-2013.02.21/example/app/whywiki_erb/view/edit.erb0000644000004100000410000000034512166103251022536 0ustar www-datawww-data<%= a("< #@page", @page) %>
innate-2013.02.21/example/app/whywiki_erb/view/index.erb0000644000004100000410000000037512166103251022723 0ustar www-datawww-data<% unless @page == 'Home' %> <%= a('< Home', :Home) %> <% end %>

<%= h @page %>

<% if @text.empty? %> <%= a("Create #@page", :edit, @page) %> <% else %> <%= a("Edit #@page", :edit, @page) %> <%= Maruku.new(@text).to_html %> <% end %> innate-2013.02.21/example/app/whywiki_erb/layout/0000755000004100000410000000000012166103251021460 5ustar www-datawww-datainnate-2013.02.21/example/app/whywiki_erb/layout/wiki.html.erb0000644000004100000410000000065312166103251024064 0ustar www-datawww-data MicroWiki <%= h @page %> <%= @content %> innate-2013.02.21/example/howto_spec.rb0000644000004100000410000000116212166103251017537 0ustar www-datawww-datarequire 'rubygems' require 'innate' class SpecMe Innate.node '/' def index "I should be at /" end def foo response['Content-Type'] = 'text/css' "I should be at /foo" end end require 'innate/spec' describe 'An example spec' do behaves_like :mock should 'respond to /' do got = get('/') got.status.should == 200 got.body.should == "I should be at /" got['Content-Type'].should == 'text/html' end should 'respond to /foo' do got = get('/foo') got.status.should == 200 got.body.should == "I should be at /foo" got['Content-Type'].should == 'text/css' end end innate-2013.02.21/example/custom_middleware.rb0000644000004100000410000000126712166103251021102 0ustar www-datawww-datarequire 'rubygems' require File.expand_path('../../lib/innate', __FILE__) class Demo Innate.node '/' def index 'Hello, World!' end def empty response.status = 405 '' end end Innate.options.mode = :dev Innate.middleware(:dev) do # Makes sure all requests and responses conform to Rack protocol use Rack::Lint # Avoid showing empty failure pages, give information when it happens. use Rack::ShowStatus # Catch exceptions inside Innate and give nice status info use Rack::ShowExceptions # Log access use Rack::CommonLogger # Reload modified files before request use Rack::Reloader # Start up the application run Innate.core end Innate.start innate-2013.02.21/example/hello.rb0000644000004100000410000000015112166103251016465 0ustar www-datawww-datarequire 'innate' class Hello Innate.node '/' def index 'Hello, World!' end end Innate.start innate-2013.02.21/example/link.rb0000644000004100000410000000061712166103251016326 0ustar www-datawww-datarequire 'innate' class Linking Innate.node '/' def index "Index links to " + a('Help?', :help) end def help "Help links to " + Different.a('A Different Node', :another) end end class Different Innate.node '/link_to' def another a('Another links even deeper', 'and/deeper') end def and__deeper Linking.a('Back to Linking Node', :index) end end Innate.start innate-2013.02.21/example/provides.rb0000644000004100000410000000140212166103251017215 0ustar www-datawww-datarequire 'rubygems' require 'innate' require 'yaml' ARTICLES = { 'hello' => { :author => 'manveru', :title => 'Hello, World!', :text => 'Some text' } } class BlogArticles Innate.node('/') # provide a content representation for requests to /.yaml # If you request `/list.yaml`, you will get the `ARTICLES object serialized # to YAML. provide(:yaml, :type => 'text/yaml'){|action, value| value.to_yaml } # Since there will always be an `html` representation (the default), you have # to take care of it. If you simply want to return an empty page, use following. provide(:html){|action, value| '' } # The return value of this method is the `value` in the provides above. def list return ARTICLES end end Innate.start innate-2013.02.21/Rakefile0000644000004100000410000000256712166103251015064 0ustar www-datawww-datarequire 'rake/clean' require 'rubygems/package_task' require 'time' require 'date' PROJECT_SPECS = FileList['spec/{innate,example}/**/*.rb'].exclude('spec/innate/cache/common.rb') PROJECT_MODULE = 'Innate' PROJECT_README = 'README.md' PROJECT_VERSION = (ENV['VERSION'] || Date.today.strftime('%Y.%m.%d')).dup DEPENDENCIES = { 'rack' => {:version => '~> 1.5.2'}, } DEVELOPMENT_DEPENDENCIES = { 'bacon' => {:version => '~> 1.2.0'}, 'rack-test' => {:version => '~> 0.6.2', :lib => 'rack/test'} } GEMSPEC = Gem::Specification.new{|s| s.name = 'innate' s.author = "Michael 'manveru' Fellinger" s.summary = "Powerful web-framework wrapper for Rack." s.description = "Simple, straight-forward base for web-frameworks." s.email = 'm.fellinger@gmail.com' s.homepage = 'http://github.com/manveru/innate' s.platform = Gem::Platform::RUBY s.version = PROJECT_VERSION s.files = `git ls-files`.split("\n").sort s.has_rdoc = true s.require_path = 'lib' s.rubyforge_project = "innate" s.required_rubygems_version = '>= 1.3.1' } DEPENDENCIES.each do |name, options| GEMSPEC.add_dependency(name, options[:version]) end DEVELOPMENT_DEPENDENCIES.each do |name, options| GEMSPEC.add_development_dependency(name, options[:version]) end Dir['tasks/*.rake'].each{|f| import(f) } task :default => [:bacon] CLEAN.include('') innate-2013.02.21/spec/0000755000004100000410000000000012166103251014337 5ustar www-datawww-datainnate-2013.02.21/spec/example/0000755000004100000410000000000012166103251015772 5ustar www-datawww-datainnate-2013.02.21/spec/example/session.rb0000644000004100000410000000117012166103251020001 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) require File.expand_path('../../../example/session', __FILE__) describe 'example/session' do behaves_like :rack_test it 'starts at 0' do get('/').body.should =~ /Value is: 0/ end it 'increments the counter' do get('/increment').body.should =~ /Value is: 1/ get('/increment').body.should =~ /Value is: 2/ get('/increment').body.should =~ /Value is: 3/ end it 'decrements the counter' do get('/decrement').body.should =~ /Value is: 2/ get('/decrement').body.should =~ /Value is: 1/ get('/decrement').body.should =~ /Value is: 0/ end end innate-2013.02.21/spec/example/app/0000755000004100000410000000000012166103251016552 5ustar www-datawww-datainnate-2013.02.21/spec/example/app/retro_games.rb0000644000004100000410000000142712166103251021412 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) require File.expand_path('../../../../example/app/retro_games', __FILE__) describe 'Retro-games app' do behaves_like :rack_test it 'lists the first game' do get '/' last_response.should =~ /1 => Pacman/ end it 'has a form to add another game' do get '/' last_response.should =~ /
'Street Fighter II') response.status.should == 302 follow_redirect! last_response.should =~ /0 => Street Fighter II/ end it 'allows you to vote for a game' do get '/vote/Street+Fighter+II' follow_redirect! last_response.should =~ /1 => Street Fighter II/ end FileUtils.rm_f('games.yaml') end innate-2013.02.21/spec/example/hello.rb0000644000004100000410000000052712166103251017426 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) require File.expand_path('../../../example/hello', __FILE__) describe 'example/hello' do behaves_like :rack_test should 'have index action' do got = get('/') got.status.should == 200 got['Content-Type'].should == 'text/html' got.body.should == 'Hello, World!' end end innate-2013.02.21/spec/example/link.rb0000644000004100000410000000134412166103251017256 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) require File.expand_path('../../../example/link', __FILE__) describe 'example/link' do behaves_like :rack_test should 'have index on Linking' do get('/').body.should == 'Index links to Help?' end should 'have help on Linking' do get('/help').body.should == "Help links to A Different Node" end should 'have another on Different' do get('/link_to/another').body. should == "Another links even deeper" end should 'have and__deeper on Different' do get('/link_to/and/deeper').body. should == "Back to Linking Node" end end innate-2013.02.21/spec/example/provides.rb0000644000004100000410000000071312166103251020153 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) require File.expand_path('../../../example/provides', __FILE__) describe 'examples/provide' do behaves_like :rack_test it 'provides YAML representation' do get '/list.yaml' last_response.body.should == ARTICLES.to_yaml last_response['Content-Type'].should == 'text/yaml' get '/list' last_response.body.should == '' last_response['Content-Type'].should == 'text/html' end end innate-2013.02.21/spec/helper.rb0000644000004100000410000000045112166103251016143 0ustar www-datawww-dataif caller_line = caller.grep(%r!spec/innate/!).first caller_file = caller_line.split(':', 2).first caller_root = File.dirname(caller_file) $0 = caller_file end require File.expand_path('../../lib/innate', __FILE__) require 'innate/spec' Innate.options.roots = [caller_root] if caller_root innate-2013.02.21/spec/innate/0000755000004100000410000000000012166103251015615 5ustar www-datawww-datainnate-2013.02.21/spec/innate/session.rb0000644000004100000410000000355012166103251017630 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) class SpecSession Innate.node('/').provide(:html, :None) def index 'No session here' end def init session[:counter] = 0 end def view session[:counter] end def increment session[:counter] += 1 end def decrement session[:counter] -= 1 end def reset session.clear end def resid session.resid! end end describe Innate::Session do behaves_like :rack_test should 'initiate session as needed' do get '/' last_response.body.should == 'No session here' last_response['Set-Cookie'].should == nil get('/init') last_response.body.should == '0' 1.upto(10) do |n| get('/increment').body.should == n.to_s end get('/reset') get('/view').body.should == '' get('/init').body.should == '0' -1.downto(-10) do |n| get('/decrement').body.should == n.to_s end end should 'set a session cookie that can be changed with #resid!' do clear_cookies get '/init' last_response['Set-Cookie'].should.not == nil old_set_cookie = last_response['Set-Cookie'] sid = Innate::Current.session.sid get '/increment' get '/view' last_response.body.should == '1' get '/resid' last_response['Set-Cookie'].should.not == nil new_sid = Innate::Current.session.sid new_sid.should.not == sid get '/view' last_response.body.should == '1' last_response['Set-Cookie'].should == nil Innate::Current.session.sid.should == new_sid # We need to verify that the old session ID has been invalidated. # The session data must be moved, not copied, on #resid!. clear_cookies set_cookie(old_set_cookie) get '/view' last_response.body.should == '' end should 'expose sid method' do Innate::Current.session.sid.should.not.be.empty end end innate-2013.02.21/spec/innate/route.rb0000644000004100000410000000557712166103251017316 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) class SpecRouter Innate.node('/').provide(:html, :None) def float(flt) "Float: %3.3f" % flt end def string(str) "String: #{str}" end def price(p) "Price: \$#{p}" end def sum(a, b) a.to_i + b.to_i end def bar 'this is bar' end end Route, Rewrite = Innate::Route, Innate::Rewrite describe Innate::Route do def check(uri, status, body = nil) got = Innate::Mock.get(uri) got.status.should == status got.body.should == body if body end should 'take lambda routers' do Route['string'] = lambda{|path, req| path if path =~ %r!^/string! } Route['string'].class.should == Proc Route['calc sum'] = lambda{|path, req| if req[:do_calc] lval, rval = req[:a, :b] rval = rval.to_i * 10 "/sum/#{lval}/#{rval}" end } Innate::Route('foo') do |path, req| '/bar' if req[:bar] end end should 'define string routes' do Route['/foobar'] = '/bar' Route['/foobar'].should == '/bar' end should 'define regex routes' do Route[%r!^/(\d+\.\d{2})$!] = "/price/%.2f" Route[%r!^/(\d+\.\d{2})$!].should == "/price/%.2f" Route[%r!^/(\d+\.\d+)!] = "/float/%.3f" Route[%r!^/(\d+\.\d+)!].should == "/float/%.3f" Route[%r!^/(\w+)!] = "/string/%s" Route[%r!^/(\w+)!].should == "/string/%s" end should 'be used at /float' do check('/123.123', 200, 'Float: 123.123') end should 'be used at /string' do check('/foo', 200, 'String: foo') end should 'use %.3f' do check('/123.123456', 200, 'Float: 123.123') end should 'resolve in the order added' do check('/12.84', 200, 'Price: $12.84') end should 'use lambda routers' do check('/string/abc', 200, 'String: abc') check('/?do_calc=1&a=2&b=6', 200, '62') end it 'should support Route() with blocks' do check('/foo?bar=1', 200, 'this is bar') end it 'should support string route translations' do check('/foobar', 200, 'this is bar') end it 'should clear routes' do Route::ROUTES.size.should > 0 Route.clear Route::ROUTES.size.should == 0 end it 'should not recurse given a bad route' do Innate::Route[ %r!^/good/(.+)$! ] = "/bad/%s" check('/good/hi', 404) end end describe Innate::Rewrite do Innate::Rewrite[ %r!^/(.+)$! ] = "/string/%s" it 'should rewrite on non-existent actions' do got = Innate::Mock.get('/hello') got.status.should == 200 got.body.should == 'String: hello' end it 'should exclude existing actions' do got = Innate::Mock.get('/bar') got.status.should == 200 got.body.should == 'this is bar' end it 'should rewite with (key, val)' do Innate::Rewrite[ %r!^/(.+)$! ] = nil Innate::Rewrite(%r!^/(.+)$!, "/string/%s") got = Innate::Mock.get('/hello') got.status.should == 200 got.body.should == 'String: hello' end end innate-2013.02.21/spec/innate/options.rb0000644000004100000410000000672512166103251017647 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) Options = Innate::Options describe Options do @options = Innate::Options.new(:spec) should 'create option' do @options.o('my name', :name, 'manveru') @options.name.should == 'manveru' end should 'create options with meta hash' do @options.o('the port', :port, 7000, :cli => '-p') @options.port.should == 7000 end should 'get complete hash via #get' do @options.get(:port)[:cli].should == '-p' @options.get(:port)[:doc].should == 'the port' end should 'get value via []' do @options[:port].should == 7000 end should 'create scope' do @options.sub(:deep) @options.deep.should.not.be.nil end should 'create option in scope' do @options.deep.o('the browser', :browser, :firefox) @options.deep.browser.should == :firefox end should 'append to scope via dsl' do @options.sub(:deep).o('hi mom', :greeting, :mom) @options.deep.greeting.should == :mom end should 'sub in subscope' do @options.sub(:deep).sub(:down).o('deep down', :me, :too) @options.deep.down.me.should == :too end should 'get sub-sub option' do @options.get(:deep, :down, :me). should == {:value => :too, :doc => 'deep down'} end should 'respond with nil on getting missing option' do @options.get(:deep, :down, :you).should.be.nil end should 'search in higher scope if key not found' do @options.deep.port.should == 7000 end should '#set_value to set a nested value directly' do @options.set_value([:deep, :down, :me], 'me deep down') @options.deep.down.me.should == 'me deep down' end should 'merge! existing options with other Enumerable' do @options.merge!(:port => 4000, :name => 'feagliir') @options.port.should == 4000 @options.name.should == 'feagliir' end should 'iterate via #each_pair' do given_keys = [:deep, :name, :port] given_values = [@options[:deep], @options[:name], @options[:port]] @options.each_pair do |key, value| given_keys.delete(key) given_values.delete(value) end given_keys.should.be.empty given_values.should.be.empty end should 'iterate via #each_option' do given_keys = [:deep, :name, :port] given_values = [@options.get(:deep), @options.get(:name), @options.get(:port)] @options.each_option do |key, option| given_keys.delete(key) given_values.delete(option) end given_keys.should.be.empty given_values.should.be.empty end should "raise when trying to assign to key that doesn't exist" do lambda{ @options[:foo] = :bar }.should.raise(ArgumentError) end should "raise when trying to assign to an option that doesn't exist" do lambda{ @options.merge!(:foo => :bar) }.should.raise(IndexError) end should 'pretty_print' do require 'pp' lines = @options.pretty_inspect.split(/\n/) lines.find_all{|l| /:doc/ === l && /:value/ === l }.size.should > 3 end should 'trigger block when option is changed' do set = nil @options.trigger(:port){|value| set = value } set.should.be.nil @options.port = 300 set.should == 300 end should 'return default value' do @options.default('my default', 'jeremy' ) @options.fake.should == 'jeremy' end should 'not change default value' do @options.fake1.should == 'jeremy' @options.fake2.should == 'jeremy' @options.fake1 = 'zurcher' @options.fake1.should == 'zurcher' @options.fake2.should == 'jeremy' end end innate-2013.02.21/spec/innate/mock.rb0000644000004100000410000000325312166103251017076 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) class SpecMock include Innate::Node map '/' def index '' end end class SpecMock2 include Innate::Node map '/deep' def index 'spec mock 2' end def foo 'spec mock 2 foo' end end describe 'Innate::SpeckMock2' do should 'handle get request' do response = Innate::Mock.get('/deep/foo') # '/foo/bar' response.status.should == 200 response.body.should == 'spec mock 2 foo' end end describe 'Innate::SpecMock' do should 'handle get request' do response = Innate::Mock.get('/') # '/one' response.status.should == 200 response.body.should == '' end should 'handle post request' do response = Innate::Mock.post('/') # '/' response.status.should == 200 response.body.should == '' end should 'handle head request' do response = Innate::Mock.head('/') response.status.should == 200 response.body.should == '' end should 'handle delete request' do response = Innate::Mock.delete('/') response.status.should == 200 response.body.should == '' end should 'handle put request' do response = Innate::Mock.put('/') response.status.should == 200 response.body.should == '' end should 'handle options request' do response = Innate::Mock.options('/') response.status.should == 200 response.body.should == '' end should 'handle connect request' do response = Innate::Mock.connect('/') response.status.should == 200 response.body.should == '' end should 'handle trace request' do response = Innate::Mock.trace('/') response.status.should == 200 response.body.should == '' end end innate-2013.02.21/spec/innate/request.rb0000644000004100000410000000560212166103251017635 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) describe Innate::Request do def request(env = {}) Innate::Request.new(@env.merge(env)) end @env = { "GATEWAY_INTERFACE" => "CGI/1.1", "HTTP_ACCEPT" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "HTTP_ACCEPT_CHARSET" => "UTF-8,*", "HTTP_ACCEPT_ENCODING" => "gzip,deflate", "HTTP_ACCEPT_LANGUAGE" => "en-us,en;q=0.8,de-at;q=0.5,de;q=0.3", "HTTP_CACHE_CONTROL" => "max-age=0", "HTTP_CONNECTION" => "keep-alive", "HTTP_HOST" => "localhost:7000", "HTTP_KEEP_ALIVE" => "300", "HTTP_USER_AGENT" => "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008123017 Firefox/3.0.4 Ubiquity/0.1.4", "HTTP_VERSION" => "HTTP/1.1", "PATH_INFO" => "/", "QUERY_STRING" => "a=b", "REMOTE_ADDR" => "127.0.0.1", "REMOTE_HOST" => "delta.local", "REQUEST_METHOD" => "GET", "REQUEST_PATH" => "/", "REQUEST_URI" => "http://localhost:7000/", "SCRIPT_NAME" => "", "SERVER_NAME" => "localhost", "SERVER_PORT" => "7000", "SERVER_PROTOCOL" => "HTTP/1.1", } should 'provide #request_uri' do request('REQUEST_URI' => '/?a=b').request_uri.should == '/?a=b' request('REQUEST_URI' => '/').request_uri.should == '/' end should 'provide #local_net?' do request.local_net?('192.168.0.1').to_s.should == '192.168.0.0' request.local_net?('252.168.0.1').should == nil request.local_net?('unknown').should == nil request('REMOTE_ADDR' => '211.3.129.47, 66.249.85.131').local_net?.should == nil request('REMOTE_ADDR' => '211.3.129.47').local_net?.should == nil end should 'provide #subset' do require 'stringio' query = {'a' => 'b', 'c' => 'd', 'e' => 'f'} params = StringIO.new(Rack::Utils.build_query(query)) req = request( 'QUERY_STRING' => params.string, 'rack.input' => params ) req.params.should == query req.subset(:a).should == {'a' => 'b'} req.subset(:a, :c).should == {'a' => 'b', 'c' => 'd'} end should 'provide #domain on http' do request('rack.url_scheme' => 'http').domain. should == URI('http://localhost:7000/') request('rack.url_scheme' => 'http').domain('/foo'). should == URI('http://localhost:7000/foo') request('rack.url_scheme' => 'http').domain('/foo', :keep_query => true). should == URI('http://localhost:7000/foo?a=b') end should 'provide #domain on https' do request('rack.url_scheme' => 'https').domain. should == URI('https://localhost:7000/') request('rack.url_scheme' => 'https').domain('/foo'). should == URI('https://localhost:7000/foo') request('rack.url_scheme' => 'https').domain('/foo', :keep_query => true). should == URI('https://localhost:7000/foo?a=b') end end innate-2013.02.21/spec/innate/cache/0000755000004100000410000000000012166103251016660 5ustar www-datawww-datainnate-2013.02.21/spec/innate/cache/common.rb0000644000004100000410000000211712166103251020476 0ustar www-datawww-dataInnate::Cache.options.names = [:one, :two] Innate::Cache.options.one = $common_cache_class Innate::Cache.options.two = $common_cache_class Innate.setup_dependencies describe $common_cache_class do cache = Innate::Cache.one @hello = 'Hello, World!' should 'store without ttl' do cache.store(:hello, @hello).should == @hello end should 'fetch' do cache.fetch(:hello).should == @hello end should 'delete' do cache.delete(:hello) cache.fetch(:hello).should == nil end should 'delete two key/value pairs at once' do cache.store(:hello, @hello).should == @hello cache.store(:innate, 'innate').should == 'innate' cache.delete(:hello, :innate) cache.fetch(:hello).should == nil cache.fetch(:innate).should == nil end should 'store with ttl' do cache.store(:hello, @hello, :ttl => 0.2) cache.fetch(:hello).should == @hello sleep 0.3 cache.fetch(:hello).should == nil end should 'clear' do cache.store(:hello, @hello) cache.fetch(:hello).should == @hello cache.clear cache.fetch(:hello).should == nil end end innate-2013.02.21/spec/innate/cache/yaml.rb0000644000004100000410000000024512166103251020150 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) $common_cache_class = Innate::Cache::YAML require File.expand_path('../../../innate/cache/common', __FILE__) innate-2013.02.21/spec/innate/cache/marshal.rb0000644000004100000410000000025012166103251020631 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) $common_cache_class = Innate::Cache::Marshal require File.expand_path('../../../innate/cache/common', __FILE__) innate-2013.02.21/spec/innate/cache/memory.rb0000644000004100000410000000024712166103251020520 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) $common_cache_class = Innate::Cache::Memory require File.expand_path('../../../innate/cache/common', __FILE__) innate-2013.02.21/spec/innate/helper.rb0000644000004100000410000000433612166103251017427 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) require 'innate/helper' module Innate module Helper module SmileHelper EXPOSE << self def smile ':)' end end module FrownHelper def frown ':(' end end module FooBarHelper def self.baz "baz" end end end end class HelperNodeExpose include Innate::Node map '/' helper :smile_helper, :frown_helper def frowny "Oh, hi #{frown}" end end describe HelperNodeExpose do should 'expose an action' do Innate::Mock.get('/smile').body.should == ':)' Innate::Mock.get('/frown').status.should == 404 Innate::Mock.get('/frowny').body.should == "Oh, hi :(" end end class FooNodeLink include Innate::Node map '/foo' helper :link, :cgi end describe Innate::Helper::Link do FNL = FooNodeLink should 'construct URI from ::r' do FNL.r(:index).should == URI('/foo/index') FNL.r(:/).should == URI('/foo/') FNL.r(:index, :foo => :bar).should == URI('/foo/index?foo=bar') uri = FNL.r(:index, :a => :b, :x => :y) uri.query.split('&').sort.should == %w[a=b x=y] end should 'construct link from ::a' do FNL.a(:index).should == 'index' FNL.a('index', :index, :x => :y).should == 'index' FNL.a('duh/bar', 'duh/bar', :x => :y).should == "duh/bar" FNL.a('foo', :/, :x => :y).should == 'foo' end should 'return module when Module is given to #each' do Innate::HelpersHelper.each_extend(self, Innate::Helper::Link) do |p| p.should == Innate::Helper::Link end end should 'raise if helpers are not found' do lambda{ Innate::HelpersHelper.each(:foo, :bar) }.should.raise(LoadError). message.should == "Helper foo not found" end should 'raise if helper is not found' do lambda{ Innate::HelpersHelper.try_require(:foo) }.should.raise(LoadError). message.should == "Helper foo not found" end should 'allow helper to be suffixed with "helper"' do Innate::HelpersHelper.get(:foo_bar).baz.should == "baz" Innate::HelpersHelper.get(:foo_bar_helper).baz.should == "baz" end end innate-2013.02.21/spec/innate/helper/0000755000004100000410000000000012166103251017074 5ustar www-datawww-datainnate-2013.02.21/spec/innate/helper/aspect.rb0000644000004100000410000000632512166103251020706 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) class AspectSpec Innate.node('/', self).provide(:html, :None) before(:with_before){ $aspect_spec_before += 40 } def with_before; $aspect_spec_before += 2; end after(:with_after){ $aspect_spec_after += 40 } def with_after; $aspect_spec_after += 2; end wrap(:with_wrap){ $aspect_spec_wrap += 20 } def with_wrap; $aspect_spec_wrap += 2; end before(:with_instance_var){ @foo = 'Hello'; @bar = 'World' } def with_instance_var; "#{@foo} #{@bar}"; end end class AspectAllSpec Innate.node('/all', self).provide(:html, :None) before_all{ $aspect_spec_before_all += 40; @foo = 'Hello'; @bar = 'World' } after_all{ $aspect_spec_after_all += 40 } def before_first; $aspect_spec_before_all +=2 ; end def before_second; $aspect_spec_before_all +=2; end def with_instance_var_first; "#{@foo} #{@bar}"; end def with_instance_var_second; "#{@foo} to the #{@bar}"; end end class AspectDerivedWithLayout < AspectAllSpec map '/derived' provide(:html, :None) layout :page def page "Content: #{@content}" end end class AspectBeforeAllCache Innate.node('/cached', self) layout :layout def self.numbers @numbers ||= [] end before_all do self.class.numbers << 10 end def index; end def layout return '#{@content}' end end class AspecNoMethodSpec Innate.node('/without_method', self) include Innate::Node map '/without_method' map_views '/' before_all{ @foo = 'Hello'; @bar = 'World'} end describe Innate::Helper::Aspect do behaves_like :rack_test it 'executes before aspect' do $aspect_spec_before = 0 get('/with_before').body.should == '42' $aspect_spec_before.should == 42 end it 'executes after asepct' do $aspect_spec_after = 0 get('/with_after').body.should == '2' $aspect_spec_after.should == 42 end it 'executes wrap aspects' do $aspect_spec_wrap = 0 get('/with_wrap').body.should == '22' $aspect_spec_wrap == 42 end it 'calls before_all and after_all' do $aspect_spec_before_all = $aspect_spec_after_all = 0 get('/all/before_first').body.should == '42' $aspect_spec_before_all.should == 42 $aspect_spec_after_all.should == 40 get('/all/before_second').body.should == '84' $aspect_spec_before_all.should == 84 $aspect_spec_after_all.should == 80 end it 'makes instance variables in blocks available to view/method' do get('/with_instance_var').body.should == 'Hello World' get('/all/with_instance_var_first').body.should == 'Hello World' get('/all/with_instance_var_second').body.should == 'Hello to the World' get('/without_method/aspect_hello').body.should == "Hello World!" end it 'calls before_all and after_all in the superclass' do $aspect_spec_before_all = $aspect_spec_after_all = 0 get('/derived/before_first').body.should == 'Content: 42' $aspect_spec_before_all.should == 42 $aspect_spec_after_all.should == 40 get('/derived/before_second').body.should == 'Content: 84' $aspect_spec_before_all.should == 84 $aspect_spec_after_all.should == 80 end it 'should not cache aspect blocks' do get('/cached') get('/cached') AspectBeforeAllCache.numbers.should == [10, 10] end end innate-2013.02.21/spec/innate/helper/cgi.rb0000644000004100000410000000212612166103251020164 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) require 'innate/helper/cgi' describe "url encode" do extend Innate::Helper::CGI it 'should url_encode strings' do # ok, I believe that the web is dumb for this # but this probably is a SHOULD thingy in the HTTP RFC url_encode('title with spaces').should == 'title+with+spaces' url_encode('[foo]').should == '%5Bfoo%5D' u('//').should == '%2F%2F' end it 'should url_decode strings' do url_decode('title%20with%20spaces').should == 'title with spaces' url_decode('title+with+spaces').should == 'title with spaces' end it 'should be reversible' do url_decode(u('../ etc/passwd')).should == '../ etc/passwd' end end describe 'html escape' do extend Innate::Helper::CGI it 'should escape html' do html_escape('& < >').should == '& < >' h('<&>').should == '<&>' end it 'should unescape html' do html_unescape('< & >').should == '< & >' end it 'should be reversible' do html_unescape(html_escape('2 > b && b <= 0')).should == '2 > b && b <= 0' end end innate-2013.02.21/spec/innate/helper/redirect.rb0000644000004100000410000000766512166103251021240 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) class SpecRedirectHelper Innate.node '/' def index self.class.name end def noop 'noop' end def redirection redirect :index end def double_redirection redirect :redirection end def redirect_referer_action redirect_referer end def redirect_referer_with_fallback redirect_referer(r(:noop)) end def no_actual_redirect catch(:redirect){ redirect(:index) } 'no actual redirect' end def no_actual_double_redirect catch(:redirect){ double_redirection } 'no actual double redirect' end def redirect_method redirect r(:noop) end def absolute_redirect redirect 'http://localhost:7000/noop' end def loop respond 'no loop' 'loop' end def respond_with_status respond 'not found', 404 end def destructive_respond respond! 'destructive' end def redirect_unmodified raw_redirect '/noop' end def redirect_with_cookie response.set_cookie('user', :value => 'manveru') redirect r(:noop) end end describe Innate::Helper::Redirect do behaves_like :rack_test @uri = 'http://localhost:7000' should 'retrieve index' do get('/').body.should =='SpecRedirectHelper' end should 'redirect' do get("#@uri/redirection") last_response.status.should == 302 last_response.headers['Location'].should == "#@uri/index" last_response.headers['Content-Type'].should == "text/html" end should 'redirect twice' do get("#@uri/double_redirection") last_response.status.should == 302 last_response.headers['Location'].should == "#@uri/redirection" last_response.headers['Content-Type'].should == "text/html" end should 'redirect to referer' do header 'REFERER', "#@uri/noop" get("#@uri/redirect_referer_action") last_response.status.should == 302 last_response.headers['Location'].should == "#@uri/noop" last_response.headers['Content-Type'].should == "text/html" end should 'redirect to fallback if referrer is identical' do header 'REFERER', "#@uri/redirect_referer_with_fallback" get("#@uri/redirect_referer_with_fallback") last_response.status.should == 302 last_response.headers['Location'].should == "#@uri/noop" last_response.headers['Content-Type'].should == "text/html" end should 'use #r' do get("#@uri/redirect_method") last_response.status.should == 302 last_response.headers['Location'].should == "#@uri/noop" last_response.headers['Content-Type'].should == "text/html" end should 'work with absolute uris' do get("#@uri/absolute_redirect") last_response.status.should == 302 last_response.headers['Location'].should == "#@uri/noop" last_response.headers['Content-Type'].should == "text/html" end should 'support #respond' do get("#@uri/loop") last_response.status.should == 200 last_response.body.should == 'no loop' end should 'support #respond with status' do get("#@uri/respond_with_status") last_response.status.should == 404 last_response.body.should == 'not found' end should 'support #respond!' do get("#@uri/destructive_respond") last_response.status.should == 200 last_response.body.should == 'destructive' end should 'redirect without modifying the target' do get("#@uri/redirect_unmodified") last_response.status.should == 302 last_response.headers['Location'].should == '/noop' end should 'catch redirection' do get("#@uri/no_actual_redirect") last_response.status.should == 200 last_response.body.should == 'no actual redirect' end should 'catch double redirect' do get("#@uri/no_actual_double_redirect") last_response.status.should == 200 last_response.body.should == 'no actual double redirect' end should 'set cookie before redirect' do get("#@uri/redirect_with_cookie") follow_redirect! last_request.cookies.should == {'user' => 'manveru'} end end innate-2013.02.21/spec/innate/helper/flash.rb0000644000004100000410000000500712166103251020520 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) class SpecFlash include Innate::Node map '/' def welcome flash[:name] = 'manveru' "Welcome #{flash[:name]}" end def bye "Bye #{flash[:name]}" end def check_empty flash.empty?.to_s end def set_delete_key flash[:name] = 'manveru' flash.delete(:name) flash[:name].to_s end def delete_key flash.delete(:name) "Bye #{flash[:name]}" end def merge! flash.merge!(:name => 'feagliir').inspect end def merge flash.merge(:name => 'feagliir').inspect end def inspect flash[:yes] = :yeah flash.inspect end def iterate flash[:yes] = :yeah elems = [] flash.each{|k,v| elems << [k,v] } elems.inspect end end class SpecFlashSub < SpecFlash map '/sub' end describe Innate::Helper::Flash do behaves_like :rack_test should 'set and forget flash twice' do get('/welcome').body.should == 'Welcome manveru' get('/bye').body.should == 'Bye manveru' get('/bye').body.should == 'Bye' get('/welcome').body.should == 'Welcome manveru' get('/bye').body.should == 'Bye manveru' get('/bye').body.should == 'Bye' end should 'work over multiple nodes' do get('/welcome').body.should == 'Welcome manveru' get('/sub/bye').body.should == 'Bye manveru' get('/sub/bye').body.should == 'Bye' get('/sub/welcome').body.should == 'Welcome manveru' get('/bye').body.should == 'Bye manveru' get('/bye').body.should == 'Bye' end should 'check if flash is empty' do get('/welcome').body.should == 'Welcome manveru' get('/check_empty').body.should == 'false' get('/check_empty').body.should == 'true' end should 'set and delete key within one request' do get('/set_delete_key').body.should == '' end should 'set and delete key over two request' do get('/welcome').body.should == 'Welcome manveru' get('/delete_key').body.should == 'Bye' end should 'merge with hash' do get('/merge').body.should == {:name => 'feagliir'}.inspect get('/bye').body.should == 'Bye' end should 'merge! with hash' do get('/merge!').body.should == {:name => 'feagliir'}.inspect get('/bye').body.should == 'Bye feagliir' end should 'inspect combined' do get('/welcome') eval(get('/inspect').body).should == {:name => 'manveru', :yes => :yeah} end should 'iterate over combined' do get('/welcome') hash = {:yes => :yeah, :name => 'manveru'} Hash[*eval(get('/iterate').body).flatten].should == hash end end innate-2013.02.21/spec/innate/helper/render.rb0000644000004100000410000000736112166103251020707 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) class SpecHelperRenderFull Innate.node '/render_full' def foo "foo: %p" % [request.params.sort] end def standard render_full(r(:foo)) end def with_query render_full(r(:foo), 'a' => 'b') end def with_session render_full(r(:get_session, :user)) end def get_session(key) session[key].inspect end def set_session(key, value) session[key] = value end end class SpecHelperRenderPartial Innate.node '/render_partial' layout :layout def standard 'hello' end def layout '{ #{@content} }' end def without_layout render_partial(:standard) end end class SpecHelperRenderView Innate.node '/render_view' map_views '/' layout :layout def standard 'hello' end def layout '{ #{@content} }' end def without_method_or_layout render_view(:num, :n => 42) end end class SpecHelperRenderMisc Innate.node '/misc' map_views '/' def recursive @n ||= 1 end end class SpecHelperRenderFile Innate.node '/render_file' layout :layout def layout '{ #{@content} }' end FILE = File.expand_path('../view/aspect_hello.xhtml', __FILE__) def absolute @bar = 'bar' render_file(FILE) end def absolute_with(foo, bar) @foo = 'foo' render_file(FILE, :foo => foo, :bar => bar) end end class SpecHelperRenderNeedsMethodView Innate.node '/render_needs_method_view' map_views '/' layout :layout trait :needs_method => true def layout '{ #{@content} }' end def without_method_or_layout render_view(:num, :n => 42) end end describe Innate::Helper::Render do describe '#render_full' do behaves_like :rack_test it 'renders a full action' do get('/render_full/standard').body.should == 'foo: []' end it 'renders full action with query parameters' do get('/render_full/with_query').body.should == 'foo: [["a", "b"]]' end # this is an edge-case, we don't have a full session running if this is the # first request from the client as Innate creates sessions only on demand # at the end of the request/response cycle. # # So we have to make some request first, in this case we simply set some # value in the session that we can get afterwards. it 'renders full action inside a session' do get('/render_full/set_session/user/manveru') get('/render_full/with_session').body.should == '"manveru"' end end describe '#render_partial' do behaves_like :rack_test it 'renders action with layout' do get('/render_partial/standard').body.should == '{ hello }' end it 'renders partial action without layout' do get('/render_partial/without_layout').body.should == '{ hello }' end end describe '#render_view' do behaves_like :rack_test it 'renders action without calling the method or applying layout' do get('/render_view/without_method_or_layout').body.should == '{ 42 }' end it 'renders action even when needs_method is true' do get('/render_needs_method_view/without_method_or_layout').body.should == '{ 42 }' end end describe 'misc functionality' do behaves_like :rack_test it 'can render_partial in a loop' do get('/misc/loop').body.scan(/\d+/).should == %w[1 2 3 4 5] end it 'can recursively render_partial' do get('/misc/recursive').body.scan(/\S/).join.should == '{1{2{3{44}3}2}1}' end end describe '#render_file' do behaves_like :rack_test it 'renders file from absolute path' do get('/render_file/absolute').body.should == '{ bar! }' end it 'renders file from absolute path with variables' do get('/render_file/absolute_with/one/two').body.should == '{ one two! }' end end end innate-2013.02.21/spec/innate/helper/link.rb0000644000004100000410000001044112166103251020356 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) class One include Innate::Node map '/' def auto_route UsingRouteSelf.new.route.to_s end end class Two include Innate::Node map '/two' def auto_route UsingRouteSelf.new.route.to_s end end class UsingRouteSelf include Innate::Helper::Link attr_reader :route def initialize @route = route_self(:elsewhere) end end describe Innate::Helper::Link do describe '#route' do should 'respond with URI for node' do One.route.should == URI('/') Two.route.should == URI('/two/') end should 'respond with URI for node with path /' do One.route('/').should == URI('/') Two.route('/').should == URI('/two/') end should 'respond with URI for node with path /foo' do One.route('/foo').should == URI('/foo') One.route(:foo).should == URI('/foo') Two.route('/foo').should == URI('/two/foo') Two.route(:foo).should == URI('/two/foo') end should 'respond with URI for node with path /foo/bar' do One.route('/foo/bar').should == URI('/foo/bar') One.route(:foo, :bar).should == URI('/foo/bar') Two.route('/foo/bar').should == URI('/two/foo/bar') Two.route(:foo, :bar).should == URI('/two/foo/bar') end should 'respond with URI for node with path /foo/bar+baz' do One.route('/foo/bar+baz').should == URI('/foo/bar+baz') One.route(:foo, 'bar baz').should == URI('/foo/bar+baz') Two.route('/foo/bar+baz').should == URI('/two/foo/bar+baz') Two.route(:foo, 'bar baz').should == URI('/two/foo/bar+baz') end should 'respond with URI for node with GET params' do One.route('/', :a => :b).should == URI('/?a=b') One.route('/foo', :a => :b).should == URI('/foo?a=b') One.route(:foo, :a => :b ).should == URI('/foo?a=b') One.route('/foo/bar', :a => :b).should == URI('/foo/bar?a=b') One.route(:foo, :bar, :a => :b).should == URI('/foo/bar?a=b') Two.route('/', :a => :b).should == URI('/two/?a=b') Two.route('foo', :a => :b).should == URI('/two/foo?a=b') Two.route(:foo, :a => :b ).should == URI('/two/foo?a=b') Two.route('/foo/bar', :a => :b).should == URI('/two/foo/bar?a=b') Two.route(:foo, :bar, :a => :b).should == URI('/two/foo/bar?a=b') end should 'prefix the links as defined in the options' do Innate.options.prefix = '/bar' One.route('/foo').should == URI('/bar/foo') Innate.options.prefix = '/' end end describe '#anchor' do should 'respond with a tag with default text' do One.anchor('hello').should == 'hello' Two.anchor('hello').should == 'hello' end should 'respond with a tag with explicit text' do One.anchor('hello', :foo).should == 'hello' Two.anchor('hello', :foo).should == 'hello' end should 'pass parameters to #route' do One.anchor('hello', :foo, :a => :b). should == 'hello' Two.anchor('hello', :foo, :a => :b). should == 'hello' end should 'escape text' do One.anchor(' & ', :foo). should == '<blink> & <a>' end should 'not append a ? when there is no query string' do One.anchor('http://google.com').include?('?').should == false end end describe 'combining #anchor and #route' do should 'not escape twice' do One.anchor('foo', One.route(:index, :bar => 'a/b/c')). should == 'foo' end should 'handle complete uris gracefully' do One.anchor('foo', 'http://example.com/?foo=bar&baz=qux'). should == 'foo' end should 'be able to route from one node to another' do Two.anchor('foo', One.route(:index)).should == 'foo' One.anchor('foo', Two.route(:index)).should == 'foo' end end describe '#route_self' do behaves_like :rack_test should 'provide a route to the node of the currently active action' do get('/auto_route').body.should == '/elsewhere' get('/two/auto_route').body.should == '/two/elsewhere' end end end innate-2013.02.21/spec/innate/helper/view/0000755000004100000410000000000012166103251020046 5ustar www-datawww-datainnate-2013.02.21/spec/innate/helper/view/partial.xhtml0000644000004100000410000000002612166103251022556 0ustar www-datawww-dataFrom Partial #{@here} innate-2013.02.21/spec/innate/helper/view/loop.xhtml0000644000004100000410000000012212166103251022070 0ustar www-datawww-data #{ render_partial('num') } innate-2013.02.21/spec/innate/helper/view/aspect_hello.xhtml0000644000004100000410000000002112166103251023557 0ustar www-datawww-data#{@foo} #{@bar}! innate-2013.02.21/spec/innate/helper/view/locals.xhtml0000644000004100000410000000001712166103251022377 0ustar www-datawww-data#{say}, #{to}! innate-2013.02.21/spec/innate/helper/view/num.xhtml0000644000004100000410000000000612166103251021717 0ustar www-datawww-data#{@n} innate-2013.02.21/spec/innate/helper/view/recursive.xhtml0000644000004100000410000000014612166103251023134 0ustar www-datawww-data{ #{@n} #{ render_partial(:recursive, :n => @n + 1) } #{@n} } innate-2013.02.21/spec/innate/response.rb0000644000004100000410000000136712166103251020007 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) class SpecResponse Innate.node '/' def index "some text" end end describe Innate::Response do describe 'Content-Type' do behaves_like :rack_test it 'responds with text/html by default' do got = get('/') got['Content-Type'].should == 'text/html' end it 'changes when option is changed' do Innate::Response.options.headers['Content-Type'] = 'text/plain' got = get('/') got['Content-Type'].should == 'text/plain' end it 'is ok with extended value' do Innate::Response.options.headers['Content-Type'] = 'text/plain; charset=utf-8' got = get('/') got['Content-Type'].should == 'text/plain; charset=utf-8' end end end innate-2013.02.21/spec/innate/dynamap.rb0000644000004100000410000000105112166103251017570 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) describe Innate::DynaMap do @app = lambda{|env| [200, {}, ['pass']] } should 'raise if nothing is mapped' do lambda{ Innate::DynaMap.call({}) }.should.raise(RuntimeError) end should 'not raise if something is mapped' do Innate.map('/', &@app) Innate::DynaMap.call('SCRIPT_NAME' => '/').should == [200, {}, ['pass']] end should 'return mapped object' do Innate.at('/').should == @app end should 'return path to object' do Innate.to(@app).should == '/' end end innate-2013.02.21/spec/innate/node/0000755000004100000410000000000012166103251016542 5ustar www-datawww-datainnate-2013.02.21/spec/innate/node/mapping.rb0000644000004100000410000000225612166103251020527 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) describe 'Node::generate_mapping' do def gen(const) Innate::Node.generate_mapping(const) end should 'transform class names into snake_case locations' do gen( 'O').should == '/o' gen( 'Oo').should == '/oo' gen( 'Ooo').should == '/ooo' gen( 'OooO').should == '/oooo' gen( 'OooOo').should == '/ooo_oo' gen('OooOoo').should == '/ooo_ooo' gen('OOOooo').should == '/oooooo' gen('OooOOO').should == '/oooooo' gen('OoOoOo').should == '/oo_oo_oo' end should 'transform namespaces into leading parts of the location' do gen('O::O').should == '/o/o' gen('O::O::O').should == '/o/o/o' gen('O::O::O::O').should == '/o/o/o/o' end should 'transform leading parts just like standalone part' do gen( 'O::O').should == '/o/o' gen( 'Oo::O').should == '/oo/o' gen( 'Ooo::O').should == '/ooo/o' gen( 'OooO::O').should == '/oooo/o' gen( 'OooOo::O').should == '/ooo_oo/o' gen('OooOoo::O').should == '/ooo_ooo/o' gen('OOOooo::O').should == '/oooooo/o' gen('OooOOO::O').should == '/oooooo/o' gen('OoOoOo::O').should == '/oo_oo_oo/o' end end innate-2013.02.21/spec/innate/node/resolve.rb0000644000004100000410000000474712166103251020562 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) class SpecNodeResolve Innate.node('/') def foo; end def bar; end def one(arg) end def two(arg1, arg2) end def more(*args) end def default(arg = nil) end end class SpecNodeResolveSub < SpecNodeResolve map '/sub' def bar(arg) end end class SpecNodeResolveIndex Innate.node('/arg') def index(arg) end end describe 'Node.resolve' do def compare(url, hash) result = SpecNodeResolve.resolve(url) result.should.not.be.nil hash.each do |key, value| result[key.to_s].should == value end end should 'resolve actions with methods' do SpecNodeResolve.resolve('/').should.be.nil SpecNodeResolve.resolve('/index').should.be.nil compare '/foo', :method => 'foo', :params => [] SpecNodeResolve.resolve('/foo/one/two').should.be.nil compare '/bar', :method => 'bar', :params => [] SpecNodeResolve.resolve('/bar/one').should.be.nil SpecNodeResolve.resolve('/one').should.be.nil compare '/one/1', :method => 'one', :params => ['1'] SpecNodeResolve.resolve('/one/1/2').should.be.nil SpecNodeResolve.resolve('/one/1/2/3').should.be.nil SpecNodeResolve.resolve('/two').should.be.nil SpecNodeResolve.resolve('/two/1').should.be.nil compare '/two/1/2', :method => 'two', :params => %w[1 2] SpecNodeResolve.resolve('/two/1/2/3').should.be.nil compare '/more', :method => 'more', :params => [] compare '/more/1', :method => 'more', :params => %w[1] compare '/more/1/2', :method => 'more', :params => %w[1 2] compare '/more/1/2/3', :method => 'more', :params => %w[1 2 3] compare '/default', :method => 'default', :params => [] compare '/default/1', :method => 'default', :params => %w[1] # NOTE: these are actually bound to fail when called, but we cannot # introspect enough to anticipate this failure compare '/default/1/2', :method => 'default', :params => %w[1 2] compare '/default/1/2/3', :method => 'default', :params => %w[1 2 3] end should 'inherit action methods from superclasses' do SpecNodeResolveSub.resolve('/foo').should.not.be.nil SpecNodeResolveSub.resolve('/foo/one/two').should.be.nil end should 'select correct method from subclasses' do SpecNodeResolveSub.resolve('/bar/one').should.not.be.nil SpecNodeResolveSub.resolve('/bar').should.be.nil end it "doesn't select index as action with index parameter if arity is 1" do SpecNodeResolveIndex.resolve('/index').should.be.nil end end innate-2013.02.21/spec/innate/node/wrap_action_call.rb0000644000004100000410000000340212166103251022367 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) SPEC_WRAP_LOG = [] class SpecWrapActionCall Innate.node '/' def first; end def second; end def third; end private def wrap_before(action) SPEC_WRAP_LOG << [:before, action.name] yield end def wrap_after(action) SPEC_WRAP_LOG << [:after, action.name] yield end end class SpecWrapActionCallStop Innate.node '/stop' def index; 'Hello'; end def wrap_pass(action) yield end def wrap_stop(action) 'No Hello' end end describe 'Node#wrap_action_call' do behaves_like :rack_test it 'executes our wrapper' do SPEC_WRAP_LOG.clear SpecWrapActionCall.add_action_wrapper(2.0, :wrap_after) get('/first') SPEC_WRAP_LOG.should == [[:after, 'first']] get('/second') SPEC_WRAP_LOG.should == [[:after, 'first'], [:after, 'second']] get('/third') SPEC_WRAP_LOG.should == [[:after, 'first'], [:after, 'second'], [:after, 'third']] end it 'executes wrappers in correct order' do SPEC_WRAP_LOG.clear SpecWrapActionCall.add_action_wrapper(1.0, :wrap_before) get('/first') SPEC_WRAP_LOG.should == [[:before, 'first'], [:after, 'first']] get('/second') SPEC_WRAP_LOG.should == [ [:before, 'first'], [:after, 'first'], [:before, 'second'], [:after, 'second']] get('/third') SPEC_WRAP_LOG.should == [ [:before, 'first'], [:after, 'first'], [:before, 'second'], [:after, 'second'], [:before, 'third'], [:after, 'third']] end it 'stops in the chain when not yielded' do SpecWrapActionCallStop.add_action_wrapper(1.0, :wrap_pass) get('/stop').body.should == 'Hello' SpecWrapActionCallStop.add_action_wrapper(2.0, :wrap_stop) get('/stop').body.should == 'No Hello' end end innate-2013.02.21/spec/innate/node/view/0000755000004100000410000000000012166103251017514 5ustar www-datawww-datainnate-2013.02.21/spec/innate/node/view/foo.html.xhtml0000644000004100000410000000004512166103251022317 0ustar www-datawww-data#{n} innate-2013.02.21/spec/innate/node/view/sub/0000755000004100000410000000000012166103251020305 5ustar www-datawww-datainnate-2013.02.21/spec/innate/node/view/sub/baz.xhtml0000644000004100000410000000002712166103251022136 0ustar www-datawww-dataThis is baz, cheer up! innate-2013.02.21/spec/innate/node/view/sub/foo/0000755000004100000410000000000012166103251021070 5ustar www-datawww-datainnate-2013.02.21/spec/innate/node/view/sub/foo/baz.xhtml0000644000004100000410000000003312166103251022716 0ustar www-datawww-dataThis is foo/baz, cheer up! innate-2013.02.21/spec/innate/node/view/only_view.xhtml0000644000004100000410000000001612166103251022602 0ustar www-datawww-dataOnly template innate-2013.02.21/spec/innate/node/view/cat2/0000755000004100000410000000000012166103251020345 5ustar www-datawww-datainnate-2013.02.21/spec/innate/node/view/cat2/cat22.xhtml0000644000004100000410000000001612166103251022333 0ustar www-datawww-dataThe 22nd cat. innate-2013.02.21/spec/innate/node/view/with_layout.xhtml0000644000004100000410000000004712166103251023143 0ustar www-datawww-data
#{@content}
innate-2013.02.21/spec/innate/node/view/cat3/0000755000004100000410000000000012166103251020346 5ustar www-datawww-datainnate-2013.02.21/spec/innate/node/view/cat3/cat33.xhtml0000644000004100000410000000002412166103251022335 0ustar www-datawww-dataThe right 33rd cat. innate-2013.02.21/spec/innate/node/view/bar.xhtml0000644000004100000410000000002712166103251021335 0ustar www-datawww-data

Hello, World!

innate-2013.02.21/spec/innate/node/view/another_layout/0000755000004100000410000000000012166103251022551 5ustar www-datawww-datainnate-2013.02.21/spec/innate/node/view/another_layout/another_layout.xhtml0000644000004100000410000000005312166103251026662 0ustar www-datawww-data
#{@content}
innate-2013.02.21/spec/innate/node/node.rb0000644000004100000410000001137412166103251020022 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) Innate.options.merge!(:views => 'view', :layouts => 'view') class SpecNode Innate.node('/') def foo; end def bar; end def one(arg) end def two(arg1, arg2) end def more(*args) end def default(arg = nil) end def cat1__cat11 'cat1: cat11' end def cat1__cat11__cat111 'cat1: cat11: cat111' end def cat3_cat33 'The wrong 33rd cat.' end end class SpecNodeProvide Innate.node('/provide') def foo '#{21 * 2}' end def bar '#{84 / 2}' end end class SpecNodeProvideTemplate Innate.node('/provide_template') map_views '/' end class SpecNodeSub < SpecNode map '/sub' def bar(arg) end end class SpecNodeWithLayout < SpecNodeProvide map '/layout' layout 'with_layout' map_layouts '/' end class SpecNodeWithLayoutView < SpecNodeProvide map '/another_layout' layout 'another_layout' map_views 'node/another_layout' map_layouts 'another_layout' end class SpecNodeWithLayoutMethod < SpecNodeProvide map '/layout_method' layout 'layout_method' def layout_method '
#{@content}
' end end class SpecNodeWithLayoutMethodSymbol < SpecNodeProvide map '/layout_method_symbol' layout :layout_method def layout_method '
#{@content}
' end end class SpecNodeWithLayoutMethodSymbolAndBlock < SpecNodeProvide map '/layout_method_symbol_block' layout(:layout_method) { |wish,path| true } def layout_method '
#{@content}
' end end class SpecNodeIndex Innate.node('/spec_index') def index "I have no parameters" end end class SpecNodeAliasView < SpecNodeProvideTemplate map '/alias_view' map_views '/' alias_view :aliased, :bar end describe 'Innate::Node' do behaves_like :rack_test should 'respond with 404 if no action was found' do got = get('/does_not_exist') got.status.should == 404 got.body.should == 'No action found at: "/does_not_exist"' got['Content-Type'].should == 'text/plain' end should 'wrap with layout' do got = get('/layout/bar') got.status.should == 200 got.body.should == %(
42
) got['Content-Type'].should == 'text/html' end should 'find layout with view_root' do got = get('/another_layout/bar') got.status.should == 200 got.body.should == %(
\n 42\n
) got['Content-Type'].should == 'text/html' end should 'find layout from method' do got = get('/layout_method/bar') got.status.should == 200 got.body.should == %(
42
) got['Content-Type'].should == 'text/html' end should 'find layout from method specified as a symbol' do got = get('/layout_method_symbol/bar') got.status.should == 200 got.body.should == %(
42
) got['Content-Type'].should == 'text/html' end should 'find layout from method specified as a symbol and a filter block' do got = get('/layout_method_symbol_block/bar') got.status.should == 200 got.body.should == %(
42
) got['Content-Type'].should == 'text/html' end should 'not get an action with wrong parameters' do got = get('/spec_index/bar') got.status.should == 404 got.body.should == 'No action found at: "/bar"' end should 'get an action view if there is no method' do got = get('/provide_template/only_view') got.status.should == 200 got.body.strip.should == "Only template" got['Content-Type'].should == 'text/html' end should 'not get an action view with params if there is no method' do got = get('/provide_template/only_view/param') got.status.should == 404 got.body.strip.should == 'No action found at: "/only_view/param"' end should 'use alias_view' do got = get('/alias_view/aliased') got.status.should == 200 got.body.strip.should == "

Hello, World!

" got['Content-Type'].should == 'text/html' end it "does double underscore lookup for method only" do got = get('/cat1/cat11') got.body.should == 'cat1: cat11' end it "does double double underscore lookup for method only" do got = get('/cat1/cat11/cat111') got.body.should == 'cat1: cat11: cat111' end it "resolves double underscore for template only" do got = get('/cat2/cat22') got.body.should == 'The 22nd cat.' end it "resolves double underscore for template and method" do got = get('/cat3/cat33') got.body.should == 'The right 33rd cat.' end it 'resolves normal template in subnode ' do got = get('/sub/baz') got.body.should == 'This is baz, cheer up!' end it 'resolves nested template in subnode' do got = get('/sub/foo/baz') got.body.should == 'This is foo/baz, cheer up!' end end innate-2013.02.21/spec/innate/action/0000755000004100000410000000000012166103251017072 5ustar www-datawww-datainnate-2013.02.21/spec/innate/action/layout.rb0000644000004100000410000000465012166103251020741 0ustar www-datawww-datarequire File.expand_path('../../../helper', __FILE__) class SpecActionLayout include Innate::Node map_layouts '/' end class SpecActionLayoutMethod < SpecActionLayout Innate.node('/from_method', self) layout('method_layout') def method_layout '
#{ @content }
' end def index 'Method Layout' end def foo "bar" end end class SpecActionLayoutFile < SpecActionLayout Innate.node('/from_file', self) layout('file_layout') def index "File Layout" end end class SpecActionLayoutSpecific < SpecActionLayout Innate.node('/specific', self) layout('file_layout'){|name, wish| name == 'index' } def index 'Specific Layout' end def without "Without wrapper" end end class SpecActionLayoutDeny < SpecActionLayout Innate.node('/deny', self) layout('file_layout'){|name, wish| name != 'without' } def index "Deny Layout" end def without "Without wrapper" end end class SpecActionLayoutMulti < SpecActionLayout Innate.node('/multi', self) layout('file_layout'){|name, wish| name =~ /index|second/ } def index "Multi Layout Index" end def second "Multi Layout Second" end def without "Without wrapper" end end class SpecIVFromView < SpecActionLayout Innate.node('/iv', self) layout :multiply def index '#{ @a = 1 }' end def multiply '#{@content} #{ @a * 2 } #{ @a * 3 }' end end describe 'Innate::Action#layout' do behaves_like :rack_test it 'uses a layout method' do get('/from_method').body.should == '
Method Layout
' get('/from_method/foo').body.should == '
bar
' end it 'uses a layout file' do get('/from_file').body.strip.should == '

File Layout

' end it 'denies layout to some actions' do get('/deny').body.strip.should == '

Deny Layout

' get('/deny/without').body.strip.should == 'Without wrapper' end it 'uses layout only for specific action' do get('/specific').body.strip.should == '

Specific Layout

' get('/specific/without').body.strip.should == 'Without wrapper' end it 'uses layout only for specific actions' do get('/multi').body.strip.should == '

Multi Layout Index

' get('/multi/second').body.strip.should == '

Multi Layout Second

' get('/multi/without').body.strip.should == 'Without wrapper' end it 'uses layout only for specific actions' do get('/iv').body.strip.should == '1 2 3' end end innate-2013.02.21/spec/innate/action/layout/0000755000004100000410000000000012166103251020407 5ustar www-datawww-datainnate-2013.02.21/spec/innate/action/layout/file_layout.xhtml0000644000004100000410000000002512166103251023776 0ustar www-datawww-data

#{ @content }

innate-2013.02.21/spec/innate/traited.rb0000644000004100000410000000245112166103251017600 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) class Animal include Innate::Traited end class Cat < Animal end class Tiger < Animal end describe Innate::Traited do should 'set trait on superclass' do Animal.trait :wild => :depends Animal.trait[:wild].should == :depends end should 'reset trait on superclass' do Animal.trait :wild => :naturally Animal.trait[:wild].should == :naturally end should 'set trait on instance' do animal = Animal.new animal.trait[:wild].should == nil animal.trait :wild => :depends animal.trait[:wild].should == :depends end should 'get ancestral trait from instance' do animal = Animal.new animal.ancestral_trait[:wild].should == :naturally animal.trait :wild => :depends animal.ancestral_trait[:wild].should == :depends end should 'set trait on subclass' do Cat.trait :sound => :meow Cat.trait[:sound].should == :meow end should 'not modify traits of other classes' do Animal.trait[:sound].should == nil Tiger.trait[:sound].should == nil end should 'get ancestral trait from class in superclass' do Cat.ancestral_trait[:wild].should == :naturally end should 'get ancestral trait from instance in superclass' do Cat.new.ancestral_trait[:wild].should == :naturally end end innate-2013.02.21/spec/innate/parameter.rb0000644000004100000410000000610212166103251020121 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) class SpecParameter include Innate::Node map '/' def index "index" end def no_params "no params" end def single_param param "single param (#{param})" end def double_param param1, param2 "double param (#{param1}, #{param2})" end def all_params *params "all params (#{params.join(', ')})" end def at_least_one param, *params "at least one (#{param}, #{params.join(', ')})" end def one_default param = 'default' "one_default (#{param})" end def cat1__cat11 'cat1: cat11' end def cat1__cat11__cat111 'cat1: cat11: cat111' end end class SpecParameter2 include Innate::Node map '/jo' def add(one, two = nil, three = nil) "#{one}:#{two}:#{three}" end def keys request.params.keys.inspect end end class SpecParameter3 include Innate::Node map '/ma' def index(*args) request.params['foo'].to_s.dump end end describe "Simple Parameters" do def handle(*url) response = Innate::Mock.get(*url) response.status.should == 200 response.body end it "Should respond to no parameters given" do handle('/no_params').should == "no params" end it "Should respond to only / with the index" do handle('/').should == "index" end it "call /bar though index doesn't take params" do lambda{ handle('/bar') }.should.raise end it "action that takes a single param" do handle('/single_param/foo').should == "single param (foo)" end it "action that takes two params" do handle('/double_param/foo/bar').should == "double param (foo, bar)" end it "action that takes two params but we give only one" do lambda{ handle('/double_param/foo') }.should.raise end it "action that takes all params" do handle('/all_params/foo/bar/foobar').should == "all params (foo, bar, foobar)" end it "action that takes all params but needs at least one" do handle('/at_least_one/foo/bar/foobar').should == "at least one (foo, bar, foobar)" end it "action that takes all params but needs at least one (not given here)" do lambda{ handle('/at_least_one') }. should.raise(ArgumentError) end it "one default" do handle('/one_default').should == "one_default (default)" end it "one default" do handle('/one_default/my_default').should == "one_default (my_default)" end it "jo/add should raise with 0 parameters" do lambda{ handle('/jo/add') }. should.raise(ArgumentError) end it "add should raise with 4 parameters" do lambda{ handle('/jo/add/1/2/3/4') }. should.raise(ArgumentError) end it "add should not raise with 1-3 parameters" do handle('/jo/add/1').should == '1::' handle('/jo/add/1/2').should == '1:2:' handle('/jo/add/1/2/3').should == '1:2:3' end it 'params should have no content without params' do handle('/ma').should == '""' end it 'should have a parameter via QUERY_PARAMS' do handle('/ma?foo=bar').should == '"bar"' end it 'should handle valueless params' do handle('/jo/keys?foo').should == '["foo"]' end end innate-2013.02.21/spec/innate/modes.rb0000644000004100000410000000257212166103251017257 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) class SpecModeDummy Innate.node '/' def index 'Hello, World!' end def random rand.to_s end end describe 'Innate modes' do describe 'dev' do behaves_like :rack_test Innate.options.mode = :dev should 'handle GET request' do get('/').status. should == 200 last_response.headers. should == {'Content-Length' => '13', 'Content-Type' => 'text/html'} last_response.body. should == 'Hello, World!' end should 'handle HEAD requests by omitting body' do head('/').status. should == 200 last_response.headers. should == {'Content-Length' => '13', 'Content-Type' => 'text/html'} last_response.body. should == '' end end describe 'live' do behaves_like :rack_test Innate.options.mode = :live should 'handle GET request' do get('/').status. should == 200 last_response.headers. should == {'Content-Length' => '13', 'Content-Type' => 'text/html'} last_response.body. should == 'Hello, World!' end should 'handle HEAD requests by omitting body' do head('/').status. should == 200 last_response.headers. should == {'Content-Length' => '13', 'Content-Type' => 'text/html'} last_response.body. should == '' end end end innate-2013.02.21/spec/innate/etanni.rb0000644000004100000410000000146712166103251017430 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) require 'innate/view/etanni' describe Etanni = Innate::Etanni do it 'renders a simple template' do etanni = Etanni.new('Hello, World!') etanni.result(self).should == 'Hello, World!' end it 'allows use of Etanni::SEPARATOR inside interplated code' do etanni = Etanni.new('Hello #{@name}') @name = "\n#{Etanni::SEPARATOR}\n" etanni.result(self).should == "Hello #{@name}" end it 'fails with SyntaxError or NameError when the SEPARATOR is used inside a template' do lambda{ etanni = Etanni.new("Hello \n#{Etanni::SEPARATOR}\n") etanni.result(self) }.should.raise NameError lambda{ etanni = Etanni.new("

Hello \n#{Etanni::SEPARATOR}\n

") etanni.result(self) }.should.raise SyntaxError end end innate-2013.02.21/spec/innate/provides/0000755000004100000410000000000012166103251017450 5ustar www-datawww-datainnate-2013.02.21/spec/innate/provides/list.html.xhtml0000644000004100000410000000010012166103251022433 0ustar www-datawww-data
  • #{user}
innate-2013.02.21/spec/innate/provides/list.txt.xhtml0000644000004100000410000000006512166103251022320 0ustar www-datawww-data#{"#{user}\n"} innate-2013.02.21/spec/innate/provides.rb0000644000004100000410000000474112166103251020003 0ustar www-datawww-datarequire File.expand_path('../../helper', __FILE__) require 'yaml' Innate.options.merge!(:views => 'provides', :layouts => 'provides') class SpecNodeProvides Innate.node '/' provide(:html, :engine => :None) provide(:yaml, :type => 'text/yaml'){|a,s| s.to_yaml } def object {'intro' => 'Hello, World!'} end def string 'Just 42' end def args(*args) args end end class SpecNodeProvidesTemplates Innate.node '/template' map_views '/' provide(:yaml, :type => 'text/yaml'){|a,s| s.to_yaml } provide(:txt, :engine => :Etanni, :type => 'text/plain') def list @users = %w[starbucks apollo athena] end end shared :assert_wish do def assert_wish(uri, body, content_type) got = get(uri) got.status.should == 200 got.body.strip.should == body.strip got['Content-Type'].should == content_type end end describe 'Content representation' do describe 'without template' do behaves_like :rack_test, :assert_wish it 'provides yaml for an object' do assert_wish('/object.yaml', {'intro' => 'Hello, World!'}.to_yaml, 'text/yaml') end it 'provides html for an object' do assert_wish('/string.html', 'Just 42', 'text/html') end it 'defaults to html presentation' do assert_wish('/string', 'Just 42', 'text/html') end it 'takes arguments with /arg1/arg2.yaml' do assert_wish('/args', [].to_s, 'text/html') assert_wish('/args.yaml', [].to_yaml, 'text/yaml') assert_wish('/args/a/b/c.yaml', ['a', 'b', 'c'].to_yaml, 'text/yaml') end end describe 'with templates' do behaves_like :rack_test, :assert_wish it 'defaults to .html.' do body = '
  • starbucks
  • apollo
  • athena
' assert_wish('/template/list', body, 'text/html') end it 'uses explicit wish for .html.' do body = '
  • starbucks
  • apollo
  • athena
' assert_wish('/template/list.html', body, 'text/html') end it 'fails when the wish cannot be satisfied' do got = get('/template/list.svg') got.status.should == 404 end it 'uses the object returned from the action method for block provides' do body = %w[starbucks apollo athena].to_yaml assert_wish('/template/list.yaml', body, 'text/yaml') end it 'uses explicit wish for .txt.' do body = "starbucks\napollo\nathena" assert_wish('/template/list.txt', body, 'text/plain') end end end innate-2013.02.21/.gems0000644000004100000410000000026512166103251014344 0ustar www-datawww-data# .gems generated gem export file. Note that any env variable settings will be missing. Append these after using a ';' field separator bacon -v1.2.0 rack -v1.5.2 rack-test -v0.6.2 innate-2013.02.21/metadata.yml0000644000004100000410000001341012166103251015707 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: innate version: !ruby/object:Gem::Version version: 2013.02.21 prerelease: platform: ruby authors: - Michael 'manveru' Fellinger autorequire: bindir: bin cert_chain: [] date: 2013-02-21 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: rack requirement: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 1.5.2 type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 1.5.2 - !ruby/object:Gem::Dependency name: bacon requirement: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 1.2.0 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 1.2.0 - !ruby/object:Gem::Dependency name: rack-test requirement: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 0.6.2 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ~> - !ruby/object:Gem::Version version: 0.6.2 description: Simple, straight-forward base for web-frameworks. email: m.fellinger@gmail.com executables: [] extensions: [] extra_rdoc_files: [] files: - .gems - .gitignore - .load_gemset - .rvmrc - .travis.yml - AUTHORS - CHANGELOG - COPYING - MANIFEST - README.md - Rakefile - example/app/retro_games.rb - example/app/todo/layout/default.xhtml - example/app/todo/spec/todo.rb - example/app/todo/start.rb - example/app/todo/view/index.xhtml - example/app/whywiki_erb/layout/wiki.html.erb - example/app/whywiki_erb/spec/wiki.rb - example/app/whywiki_erb/start.rb - example/app/whywiki_erb/view/edit.erb - example/app/whywiki_erb/view/index.erb - example/custom_middleware.rb - example/hello.rb - example/howto_spec.rb - example/link.rb - example/provides.rb - example/session.rb - innate.gemspec - lib/innate.rb - lib/innate/action.rb - lib/innate/adapter.rb - lib/innate/cache.rb - lib/innate/cache/api.rb - lib/innate/cache/drb.rb - lib/innate/cache/file_based.rb - lib/innate/cache/marshal.rb - lib/innate/cache/memory.rb - lib/innate/cache/yaml.rb - lib/innate/current.rb - lib/innate/default_middleware.rb - lib/innate/dynamap.rb - lib/innate/helper.rb - lib/innate/helper/aspect.rb - lib/innate/helper/cgi.rb - lib/innate/helper/flash.rb - lib/innate/helper/link.rb - lib/innate/helper/redirect.rb - lib/innate/helper/render.rb - lib/innate/log.rb - lib/innate/log/color_formatter.rb - lib/innate/log/hub.rb - lib/innate/lru_hash.rb - lib/innate/mock.rb - lib/innate/node.rb - lib/innate/options.rb - lib/innate/options/dsl.rb - lib/innate/options/stub.rb - lib/innate/request.rb - lib/innate/response.rb - lib/innate/route.rb - lib/innate/session.rb - lib/innate/session/flash.rb - lib/innate/spec.rb - lib/innate/spec/bacon.rb - lib/innate/state.rb - lib/innate/state/accessor.rb - lib/innate/traited.rb - lib/innate/trinity.rb - lib/innate/version.rb - lib/innate/view.rb - lib/innate/view/erb.rb - lib/innate/view/etanni.rb - lib/innate/view/none.rb - spec/example/app/retro_games.rb - spec/example/hello.rb - spec/example/link.rb - spec/example/provides.rb - spec/example/session.rb - spec/helper.rb - spec/innate/action/layout.rb - spec/innate/action/layout/file_layout.xhtml - spec/innate/cache/common.rb - spec/innate/cache/marshal.rb - spec/innate/cache/memory.rb - spec/innate/cache/yaml.rb - spec/innate/dynamap.rb - spec/innate/etanni.rb - spec/innate/helper.rb - spec/innate/helper/aspect.rb - spec/innate/helper/cgi.rb - spec/innate/helper/flash.rb - spec/innate/helper/link.rb - spec/innate/helper/redirect.rb - spec/innate/helper/render.rb - spec/innate/helper/view/aspect_hello.xhtml - spec/innate/helper/view/locals.xhtml - spec/innate/helper/view/loop.xhtml - spec/innate/helper/view/num.xhtml - spec/innate/helper/view/partial.xhtml - spec/innate/helper/view/recursive.xhtml - spec/innate/mock.rb - spec/innate/modes.rb - spec/innate/node/mapping.rb - spec/innate/node/node.rb - spec/innate/node/resolve.rb - spec/innate/node/view/another_layout/another_layout.xhtml - spec/innate/node/view/bar.xhtml - spec/innate/node/view/cat2/cat22.xhtml - spec/innate/node/view/cat3/cat33.xhtml - spec/innate/node/view/foo.html.xhtml - spec/innate/node/view/only_view.xhtml - spec/innate/node/view/sub/baz.xhtml - spec/innate/node/view/sub/foo/baz.xhtml - spec/innate/node/view/with_layout.xhtml - spec/innate/node/wrap_action_call.rb - spec/innate/options.rb - spec/innate/parameter.rb - spec/innate/provides.rb - spec/innate/provides/list.html.xhtml - spec/innate/provides/list.txt.xhtml - spec/innate/request.rb - spec/innate/response.rb - spec/innate/route.rb - spec/innate/session.rb - spec/innate/traited.rb - tasks/authors.rake - tasks/bacon.rake - tasks/changelog.rake - tasks/gem.rake - tasks/gem_setup.rake - tasks/grancher.rake - tasks/manifest.rake - tasks/rcov.rake - tasks/release.rake - tasks/reversion.rake - tasks/setup.rake - tasks/ycov.rake homepage: http://github.com/manveru/innate licenses: [] post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: 1.3.1 requirements: [] rubyforge_project: innate rubygems_version: 1.8.25 signing_key: specification_version: 3 summary: Powerful web-framework wrapper for Rack. test_files: [] innate-2013.02.21/CHANGELOG0000644000004100000410000036525512166103251014637 0ustar www-datawww-data[866c9cd | 2013-02-21 12:21:46 UTC] Michael Fellinger * Version 2013.02.21 [aa22191 | 2013-02-21 12:21:16 UTC] Michael Fellinger * update dependencies [1a2ee39 | 2013-02-07 00:10:01 UTC] Michael Fellinger * Version 2013.02 [64ca67a | 2013-01-29 23:34:26 UTC] Michael Fellinger * don't do CI for REE, it's not supported anymore, add rbx and jruby 1.9 [079975c | 2013-01-29 21:57:39 UTC] Yorick Peterse * Preserve values when calling render_full. Signed-off-by: Yorick Peterse [a90d3f9 | 2013-01-29 21:53:16 UTC] Yorick Peterse * Fix for generting URLs using anchor(). Instead of always appending "?" to the URL the anchor() method should only do so when there actually is a query string. Signed-off-by: Yorick Peterse [d2aeb7f | 2013-01-29 21:17:08 UTC] Yorick Peterse * Caching of provides and method arities. Caching of a controller's provide handlers as well as the method arities can lead to a nice performance boost of around 300 transactions/second using the following benchmark: require 'innate' Innate.middleware :live do run Innate.core end Innate::Log.level = Logger::ERROR Innate.options.mode = :live ENV['RACK_ENV'] = 'none' class MainController Innate.node('/', self) def index return 'index' end end [:fast_mappings, :cache_provides, :cache_method_arities].each do |key| MainController.ancestral_trait[key] = true end Innate.start(:adapter => :thin) Benchmarking this was done by running `siege -c 10 -t 5s -b HOST` and would initially result in around 1700 trans/sec. When using this commit this sits between 2000/2100 trans/sec. To prevent any potential issues the caching of provides and method aritites is disabled by default. See Github issue #7 for more information. Signed-off-by: Yorick Peterse [06dd4c5 | 2013-01-29 18:25:49 UTC] Yorick Peterse * Revert action caching. Instead of caching the entire action instance (which is modified further down the chain) various parts that make up this process will be cached instead (where possible). Signed-off-by: Yorick Peterse [32440b0 | 2013-01-15 18:38:41 UTC] Michael Fellinger * prevent memory leak from action caching [040d084 | 2013-01-15 18:37:19 UTC] Michael Fellinger * clean up LRUHash a bit [a136a72 | 2013-01-14 20:06:22 UTC] Michael Fellinger * build middleware only once [8aea7cb | 2013-01-14 18:31:37 UTC] Yorick Peterse * Only compile middleware for the current mode. Signed-off-by: Yorick Peterse [1da947d | 2012-12-07 21:25:01 UTC] Michael Fellinger * Version 2012.12 [71dc65d | 2012-12-07 20:24:57 UTC] Yorick Peterse * Fixed YARD formatting errors. Signed-off-by: Yorick Peterse [b441fe6 | 2012-12-05 23:18:02 UTC] Yorick Peterse * Properly reference to Innate.app. Signed-off-by: Yorick Peterse [1746fe4 | 2012-12-05 22:24:02 UTC] Yorick Peterse * Easier way of defining custom middleware. Instead of requiring developers to monkey-patch the Innate module in order to add their own middleware people can now use `Innate.middleware` similar to the traditional `Innate.middleware!` method. Example use: Innate.middleware(:dev) do use Rack::Head use Rack::Reloader, 2 run Innate.core end Signed-off-by: Yorick Peterse [42e6a33 | 2012-10-03 22:36:50 UTC] Yorick Peterse * Call `Innate.app` instead of `self.app`. Signed-off-by: Yorick Peterse [4988aa7 | 2012-10-03 22:03:46 UTC] Yorick Peterse * Fixed Innate.start! The class method Innate.start! was still relying on the no longer existing instance variable `@middleware`. This method has been modified to use `Innate.app` instead. Signed-off-by: Yorick Peterse [6d73762 | 2012-10-03 21:44:03 UTC] Yorick Peterse * Removed debugging code and fixed tests. Various ``p`` statements that were used for debugging purposes have been removed. I've also fixed the broken specifications by defining `Innate.middleware_spec`. Looking at this requirement I'm not entirely sure if having to define a new method for a custom mode is the way to go. While it certainly keeps things simple it should be documented *very clearly* if we stick with this. Mentioning the following people for feedback on this: @manveru, @leucos. Signed-off-by: Yorick Peterse [055454e | 2012-09-24 16:04:05 UTC] Michael Fellinger * fix startup with middleware [9f2943e | 2012-08-09 17:03:05 UTC] Yorick Peterse * Clarify the use of blocks when calling provide(). Signed-off-by: Yorick Peterse [9b343b8 | 2012-03-22 18:16:47 UTC] Yorick Peterse * Documented the Aspect helper. This commit fixes #6. Signed-off-by: Yorick Peterse [f3bfa25 | 2012-03-17 12:17:40 UTC] Michael Fellinger * ignore rbx-19mode [d76cf9c | 2012-03-15 21:55:45 UTC] Yorick Peterse * Innate.start no longer takes a block. Signed-off-by: Yorick Peterse [fbd82c0 | 2012-03-15 20:11:12 UTC] Yorick Peterse * No need to call require 'socket'. Signed-off-by: Yorick Peterse [14ff7ef | 2012-03-13 22:41:29 UTC] Michael Fellinger * add action caching for double the speed for half the work [8e360c3 | 2012-03-10 11:01:17 UTC] Michael Fellinger * get rid of MiddlewareCompiler and RackFileWrapper [f133be7 | 2012-03-07 18:27:47 UTC] Michael Fellinger * Version 2012.03 [cab2aef | 2012-03-07 18:27:21 UTC] Michael Fellinger * update dependency to rack 1.4.1 [e474964 | 2012-03-01 19:22:58 UTC] Yorick Peterse * Fixed various YARD formatting issues. Signed-off-by: Yorick Peterse [d82fd1e | 2012-02-26 13:22:09 UTC] Michael Fellinger * Enable the render helper to render views without corresponding method if needs_method is enabled [918974e | 2012-02-26 12:45:50 UTC] Michael Fellinger * Fix initialize of Rack::Cascade on 1.4.1 [0e298de | 2011-12-28 17:57:58 UTC] Michael Fellinger * Here comes a better Innate::Cache::register, now with less warnings and more speed [d8a1da4 | 2011-12-28 05:06:07 UTC] Michael Fellinger * Version 2011.12 [13f9372 | 2011-12-28 04:54:29 UTC] Michael Fellinger * less obfuscation ftw [10cf300 | 2011-12-28 04:54:09 UTC] Michael Fellinger * minor cleanup around specs [7f61483 | 2011-12-28 04:53:40 UTC] Michael Fellinger * Update to Rack 1.4.0 [575e900 | 2011-12-08 17:05:04 UTC] Michael Fellinger * Update travis config [037f35a | 2011-11-06 12:18:30 UTC] Yorick Peterse * Revert "AOP calls can now be stacked." This reverts commit 3ceb18dae7b774ab9b21cba6538b217ba35d5e21. Signed-off-by: Yorick Peterse [3ceb18d | 2011-11-06 11:30:51 UTC] Yorick Peterse * AOP calls can now be stacked. This means that calling methods such as before_all() or before() multiple times in the same controller will no longer in these calls overwriting previously defined ones. A short example of this is the following: class Posts Innate.node('/posts') helper :aspect NUMBERS = [] before_all do NUMBERS << 10 end before_all do NUMBERS << 20 end def index return NUMBERS end end Visiting /posts would result in "[10, 20]" being displayed in the browser. Signed-off-by: Yorick Peterse [7ad5d81 | 2011-10-23 17:19:58 UTC] Michael Fellinger * Version 2011.10 [013b148 | 2011-10-22 20:12:45 UTC] Michael Fellinger * Remove deprecated Innate::Session.options.expires, use Innate::Session.options.ttl instead [ae24452 | 2011-10-22 20:10:57 UTC] Michael Fellinger * Remove deprecated shared :mock block [7bf2528 | 2011-10-21 23:41:34 UTC] Michael Fellinger * Another 1.8 incompatibility in the spec [97cf46a | 2011-10-21 23:39:23 UTC] Michael Fellinger * Make provides spec more robust [11bdba7 | 2011-10-21 22:38:16 UTC] Michael Fellinger * Try requiring rubygems for the lesser versions [8dcfffb | 2011-10-21 22:35:20 UTC] Michael Fellinger * Remove set -x, let's get down to business [7a5066f | 2011-10-21 22:33:25 UTC] Michael Fellinger * Try ignoring trust issues with .rvmrc [f913028 | 2011-10-21 22:16:06 UTC] Michael Fellinger * Load rvm manually [3791189 | 2011-10-21 22:14:12 UTC] Michael Fellinger * turn debugging for rvm on [845c834 | 2011-10-21 22:11:44 UTC] Michael Fellinger * Try debugging and loading bashrc to get rvm [85ff8df | 2011-10-21 22:09:46 UTC] Michael Fellinger * And make things a bit more complicated [e725da7 | 2011-10-21 21:58:22 UTC] Michael Fellinger * try to make travis happy [acaa77a | 2011-10-21 21:55:48 UTC] Michael Fellinger * Move rvm gemset import to the right place [ac0371c | 2011-10-21 16:30:40 UTC] Michael Fellinger * Try setup via .rvmrc .gems [156e09b | 2011-10-21 16:30:21 UTC] Michael Fellinger * Remove dependency on json [b5ca6a3 | 2011-10-21 15:53:08 UTC] Michael Fellinger * Run setup before bacon [0426977 | 2011-10-21 15:47:21 UTC] Michael Fellinger * Revert "Remove the unused gem install task" This reverts commit 3e1cc52743470886f7b50db633535bcf6765b638. [3e1cc52 | 2011-10-21 15:36:30 UTC] Michael Fellinger * Remove the unused gem install task [9390547 | 2011-10-21 15:36:15 UTC] Michael Fellinger * Fix location of RUBY [f086a10 | 2011-10-21 15:35:46 UTC] Michael Fellinger * Fix the gem package task [bed5d5a | 2011-10-21 15:35:02 UTC] Michael Fellinger * Update rvmrc [965ed57 | 2011-10-21 15:20:10 UTC] Michael Fellinger * Adding travis config [e9b0d7c | 2011-09-23 10:06:54 UTC] Yorick Peterse * Updated the README, fixes #5 Signed-off-by: Yorick Peterse [157a09d | 2011-08-18 08:00:28 UTC] YorickPeterse * Added a .rvmrc file and updated the .gitignore file to exclude rcov data. [7df330c | 2011-07-20 08:09:53 UTC] Michael Fellinger * Update spec file exclusion [a4eb56a | 2011-06-01 23:07:46 UTC] Michael Fellinger * Update Node documentation [d05190a | 2011-04-19 09:37:16 UTC] Michael Fellinger * Version 2011.04 [bacc603 | 2011-04-19 09:37:03 UTC] Michael Fellinger * Remove rubyforge release task [05ccf96 | 2011-04-19 09:31:28 UTC] Michael Fellinger * Node::find_method must accept anything that responds to #to_s as method name [8d4bfd0 | 2011-02-14 07:07:12 UTC] Michael Fellinger * Don't mention :state, it's gone [2b3a9ca | 2011-01-26 14:12:26 UTC] Michael Fellinger * Version 2011.01 [6039ffa | 2010-12-11 21:58:04 UTC] Michael Fellinger * Adjust spec for changes in Rack [5e30254 | 2010-09-17 17:58:10 UTC] Antti Tuomi * New method for Innate::Session, #resid!, that can be used to change the session key. The intent of the method is to allow changing session keys when user logs in to prevent certain session fixation attack vectors. #resid! moves all session data under a new session key and thus invalidates the old key. It is probably a good idea to explicitly reset the session data as well on login, but the necessity of this depends on the application. [85d45ea | 2010-09-07 08:14:44 UTC] Lee Jarvis * updated git url [51eac73 | 2010-09-07 06:25:22 UTC] Lee Jarvis * added gitignore [32c943c | 2010-09-06 13:02:25 UTC] Lee Jarvis * fixed pointless spec addition [b180c1c | 2010-09-06 13:00:44 UTC] Lee Jarvis * added specs for helper suffix [c7fccc6 | 2010-09-06 12:50:45 UTC] Lee Jarvis * removed send_file helper spec [49c9963 | 2010-09-06 12:49:54 UTC] Lee Jarvis * removed send_file from default helpers [4ca7b0c | 2010-09-06 12:22:23 UTC] Lee Jarvis * allow helper modules to be suffixed with 'helper' this allows us to create helpers which may have identical names as Models without having namespace conflicts [7d8437e | 2010-08-26 22:12:26 UTC] Michael Fellinger * Support HttpOnly [1183bca | 2010-08-20 21:15:58 UTC] Lee Jarvis * moved send_file helper to ramaze [6412640 | 2010-07-21 11:32:15 UTC] injekt * fixed readme formatting [1ac3e6f | 2010-07-21 11:31:27 UTC] injekt * updated installation docs [f4ecc85 | 2010-07-11 23:34:26 UTC] Michael Fellinger * Version 2010.07 [d11be17 | 2010-07-11 23:24:19 UTC] Michael Fellinger * Fix issue with Ruby 1.9.2 [154fdf8 | 2010-06-30 13:53:50 UTC] Michael Fellinger * Fix typo [231b0ee | 2010-06-17 22:40:37 UTC] Michael Fellinger * Version 2010.06.18 [ce8b903 | 2010-06-17 22:40:10 UTC] Michael Fellinger * Allow latest version of Rack [dbaaeb5 | 2010-06-03 15:00:56 UTC] Lee Jarvis * edited documentation for render_view [55bf889 | 2010-05-04 09:29:07 UTC] Michael Fellinger * Remove AccessLog option from webrick handler to avoid log duplication [32886da | 2010-04-11 11:42:13 UTC] Zoxc * Updated Etanni specs. [9bf55e5 | 2010-04-11 11:30:17 UTC] Zoxc * Some tweaks to Etanni. [3502814 | 2010-04-09 16:49:07 UTC] Michael Fellinger * Major speedup for Etanni as suggested by Zoxc [b796644 | 2010-04-04 07:56:06 UTC] Michael Fellinger * Version 2010.04 [1aeacca | 2010-04-03 21:45:46 UTC] injekt * fixed redirect spec [0a71ec2 | 2010-04-03 21:42:52 UTC] injekt * fixed redirect spec [6eedc76 | 2010-03-29 21:07:51 UTC] injekt * minor fixes to README [b5787a4 | 2010-03-29 15:31:03 UTC] injekt * Added support for case-insensitive View lookups Removed case sensitive restriction when using Controller::engine for View lookup; :haml is as good as :Haml [edc00df | 2010-03-27 22:55:07 UTC] injekt * fixed doc for flash helper (depreciated method) [2e4bdbd | 2010-03-24 14:18:35 UTC] Michael Fellinger * Add spec for how to pass arguments to provide actions [d09ff45 | 2010-03-19 00:37:27 UTC] Michael Fellinger * Fix some issues, don't split Content-Type at all [abe842c | 2010-03-19 00:33:41 UTC] Michael Fellinger * Make sure ; doesn't break Content-Type [acce333 | 2010-03-18 11:26:03 UTC] Michael Fellinger * The Response Content-Type option should influence default mime type [7ad4de7 | 2010-03-11 12:44:42 UTC] crab * use Innate.options.prefix as redirect fallback [e13e2b2 | 2010-03-09 09:48:06 UTC] Michael Fellinger * Fix .dup in Rakefile [4fa40fc | 2010-03-08 21:53:00 UTC] Michael Fellinger * Version 2010.03 [c48a647 | 2010-02-03 15:59:05 UTC] Michael Fellinger * Add a spec for Etanni [baa0dd8 | 2010-01-17 14:57:44 UTC] Michael Fellinger * clarify precedence [c9fa60f | 2010-01-06 15:14:40 UTC] Michael Fellinger * Set correct header in referrer spec [59f03da | 2010-01-06 15:10:22 UTC] Michael Fellinger * Fix request spec for new rack behaviour [82cd8d9 | 2010-01-06 14:53:24 UTC] Michael Fellinger * Version 2010.01 [2511e2b | 2010-01-06 14:52:49 UTC] Michael Fellinger * Update Rakefile [07f9238 | 2009-12-01 22:57:56 UTC] Michael Fellinger * Revert "Major performance improvement for Etanni." This reverts commit 1b736b793e9f31cf79fad2820f3f20a00802c2c8. [1b736b7 | 2009-12-01 03:17:23 UTC] Zoxc * Major performance improvement for Etanni. [7b14652 | 2009-11-30 17:50:01 UTC] Zoxc * Performance improvement for Etanni. [17dba1a | 2009-11-19 03:12:29 UTC] Michael Fellinger * Remove comment [aac4faf | 2009-11-16 21:16:56 UTC] Lin Jen-Shin * [helper/render.rb] dup on variables arg is not needed. never refered. [5d1e95d | 2009-11-16 20:52:12 UTC] Lin Jen-Shin * [helper/render.rb] fixed render_file's sync_variables. see detail: This line syncs variables from current action to newly created action: action.sync_variables(self.action) but later this line eliminates above effect: action.variables = variables.dup Assume we would like variables from current action, but would like to override (or hide, shadow) them by passing another hash of variables in render_file's second arguments. Then change that line to: action.variables.merge!(variables.dup) spec this behavior in SpecHelperRenderFile. [42b5ec5 | 2009-10-28 20:43:54 UTC] Lin Jen-Shin * Add a simple Unicorn wrapper in innate/adapter.rb [14a340f | 2009-10-18 01:01:48 UTC] Michael Fellinger * Allow skipping the template discovery to speed things up [d02bd71 | 2009-10-18 00:50:51 UTC] Michael Fellinger * Fix gem_setup task [0f3c5fe | 2009-10-05 16:32:30 UTC] Michael Fellinger * Allow for change of the default action name as proposed by Daniel Azuma [ee96b28 | 2009-10-04 15:37:44 UTC] Michael Fellinger * Remove temp README [3e90299 | 2009-10-04 15:37:07 UTC] Michael Fellinger * Fix precedence issue in redirect_referer [44f40da | 2009-10-03 21:33:11 UTC] Arnaud Meuret * Typos and minor rephrasing. [7ad5fd9 | 2009-10-02 22:04:37 UTC] Michael Fellinger * Sync metadata after release [1b0702f | 2009-10-02 20:24:16 UTC] Michael Fellinger * Version 2009.10 [88451a1 | 2009-10-02 20:23:53 UTC] Michael Fellinger * Improve the release tasks, add one for gemcutter [c37df32 | 2009-10-01 18:16:02 UTC] Arnaud Meuret * Fix: specifying a layout from a method and a filter block was broken [18668be | 2009-09-29 21:13:13 UTC] Michael Fellinger * Update dependencies [672bbaa | 2009-09-22 22:15:44 UTC] Michael Fellinger * Use Rack::Utils::build_query, this changes query separator from ; to & [0d4d2d1 | 2009-09-22 22:04:05 UTC] Michael Fellinger * Improve code readability a bit [44d02ed | 2009-09-22 00:02:09 UTC] Michael Fellinger * Use Mutex instead of Thread::critical [1b80af6 | 2009-09-22 00:00:42 UTC] Michael Fellinger * Fix ruby/jruby dependency mixup [783f554 | 2009-09-21 23:32:07 UTC] Michael Fellinger * Fix startup issue regarding jruby-rack [a908b32 | 2009-09-15 14:15:48 UTC] Michael Fellinger * Fix typo [79df3a5 | 2009-08-27 15:21:05 UTC] Michael Fellinger * Don't call aspects in layout [b69e9dd | 2009-08-27 10:55:08 UTC] Michael Fellinger * Fix Options#pretty_print spec [6b8c32d | 2009-08-27 10:36:53 UTC] Michael Fellinger * dev dependencies for jruby [0bb6ea5 | 2009-08-26 23:59:01 UTC] Michael Fellinger * Forgot to require digest/md5 [2bc0566 | 2009-08-19 15:27:37 UTC] Michael Fellinger * Cache is not a module [c74c2b8 | 2009-08-17 12:37:02 UTC] Michael Fellinger * fix doc typo [9650f8c | 2009-07-28 13:49:20 UTC] Michael Fellinger * Some more specs for double underscore [822560a | 2009-07-28 13:43:32 UTC] Michael Fellinger * Expand specs for double underscore [b865335 | 2009-05-21 20:27:38 UTC] Antti Tuomi * Aspect spec uses inline layout instead a file-based. Also prefixed DerivedWithLayout with the helper name. Signed-off-by: Michael Fellinger [62d8853 | 2009-05-21 20:16:57 UTC] Antti Tuomi * Aspect spec checks the functionality when using layouts. This spec fails at the moment. Signed-off-by: Michael Fellinger [e4735cb | 2009-05-27 21:57:48 UTC] ravage * Resolve fake depth Signed-off-by: Michael Fellinger [10d7ef3 | 2009-07-21 23:11:57 UTC] Jérémy Zurcher * fix default option handling overriding in options/dsl Signed-off-by: Michael Fellinger [03274f3 | 2009-07-19 10:02:21 UTC] Michael Fellinger * Version 2009.07 [3ed8553 | 2009-07-19 10:01:48 UTC] Michael Fellinger * Update dependencies [4e09c15 | 2009-07-06 17:12:43 UTC] Michael Fellinger * Implement an OpenSSL fallback for Session IDs Comes into play in case SecureRandom cannot be found. This should cover 99% of all < 1.8.7 installs. [cf9cdce | 2009-07-02 15:05:45 UTC] Michael Fellinger * More intelligent gem_setup to handle cases where a library can be found via require but ain't a gem [337f092 | 2009-07-02 15:05:02 UTC] Michael Fellinger * Use absolute paths for spec requires [7a475b9 | 2009-06-14 21:14:47 UTC] Michael Fellinger * Require rubygems >= 1.3.1 [7f41b89 | 2009-06-12 19:54:32 UTC] Michael Fellinger * Version 2009.06.12 [e92a8b3 | 2009-06-11 22:41:35 UTC] Michael Fellinger * Make sure that instance-variables set in the view template can be used in the layout [84ce0d8 | 2009-06-03 18:09:09 UTC] Michael Fellinger * Fix the bacon task dependency [46de89c | 2009-06-02 18:50:26 UTC] Michael Fellinger * Version 2009.06 [e05a004 | 2009-06-02 18:49:17 UTC] Michael Fellinger * Use rubygems development-dependencies, improve rake setup [2575c64 | 2009-06-01 12:46:46 UTC] Michael Fellinger * Allow passing Innate.start(:root => [path1, path2]) [5104984 | 2009-06-01 12:11:26 UTC] Michael Fellinger * Move innate/spec to innate/spec/bacon and make innate/spec require that [9047159 | 2009-06-01 12:08:17 UTC] Michael Fellinger * Deprecate behaves_like(:mock), use behaves_like(:rack_test) instead [ba27790 | 2009-06-01 12:07:42 UTC] Michael Fellinger * Fix Request#subset spec for latest Rack [e0bb6db | 2009-05-28 15:05:35 UTC] Michael Fellinger * Make the cookie ttl optional [76e4377 | 2009-05-22 16:04:37 UTC] Michael Fellinger * Allow #write on the logger [3890ba7 | 2009-05-19 09:38:31 UTC] Michael Fellinger * Fix some yard tags [18002ee | 2009-05-16 12:32:55 UTC] Michael Fellinger * Iterate logging arguments before they reach the logger [8d43aad | 2009-05-16 11:15:46 UTC] Michael Fellinger * Try to improve render_file so it works form anywhere [8f5d193 | 2009-05-14 22:22:54 UTC] Michael Fellinger * Reverse order in middleware [9c3b2b9 | 2009-05-09 14:25:14 UTC] Michael Fellinger * Deprecate Innate::Session.options.expires, use ttl instead. Set maximum ttl to 30 days [d343c9e | 2009-05-08 11:16:50 UTC] Ryan Grove * Make Innate::Session.sid public Signed-off-by: Michael Fellinger [89c79de | 2009-05-06 21:42:03 UTC] Pistos * Adjusted pretty_print spec again. Made it looser, since we don't really care much about it because it doesn't significantly affect Ramaze functionality. Signed-off-by: Michael Fellinger [220ae9e | 2009-05-05 19:43:51 UTC] Pistos * Adjusted Innate::Options#pretty_print spec to work across more systems and conditions, yet still test something non-trivial. Signed-off-by: Michael Fellinger [e51e888 | 2009-05-06 22:50:47 UTC] Michael Fellinger * Polish things a bit more where they went wrong during release [5138050 | 2009-05-06 22:38:00 UTC] Michael Fellinger * Version 2009.05 [9486b35 | 2009-05-06 22:37:19 UTC] Michael Fellinger * VERSION=xxx rake release:xxx [14feedf | 2009-05-06 22:33:48 UTC] Michael Fellinger * Bring rakefile up to date [2252c28 | 2009-05-06 22:20:19 UTC] Michael Fellinger * Last minute changes to tasks [ddc4560 | 2009-05-06 22:14:56 UTC] Michael Fellinger * Add some ycov tasks, not all that tested yet [146e349 | 2009-05-06 19:56:27 UTC] Michael Fellinger * raise a more meaningful error when trying to assign to a non-existent option [21bbd9b | 2009-05-05 13:08:06 UTC] Michael Fellinger * Remove some (c) [8fd62a3 | 2009-05-05 11:48:32 UTC] Michael Fellinger * Make Session compatible with the Rack spec, prepare to make it a middleware [a73a54e | 2009-05-05 11:37:25 UTC] Michael Fellinger * Tell people that using YAML/Marshal cache is a bad idea in some cases [fff4e2a | 2009-05-05 11:30:24 UTC] Michael Fellinger * Some docs fixes [d90138c | 2009-05-04 18:19:35 UTC] Ryan Grove * Add a read_cache option (off by default) to control caching of template files on read [aaa9b96 | 2009-05-03 11:04:18 UTC] Ryan Grove * When the view cache is enabled and Innate is in :live mode, cache view files after the first read to prevent unnecessary filesystem reads in the future. [06c224f | 2009-05-04 23:49:15 UTC] Michael Fellinger * Fix update_mapping_shared, it would try to walk files and was buggy [e3ad651 | 2009-05-04 10:28:49 UTC] Michael Fellinger * remove specs for state [f69716d | 2009-05-04 00:37:06 UTC] Michael Fellinger * Implement caching of traits [0434785 | 2009-05-02 22:56:05 UTC] Michael Fellinger * Remove useless token from Etanni [d0356c6 | 2009-05-02 13:05:42 UTC] Michael Fellinger * Use clearer syntax for the option in view [2c3c1ca | 2009-05-02 12:40:54 UTC] Michael Fellinger * Elaborate what +filename+ means [12d3666 | 2009-05-02 12:40:40 UTC] Michael Fellinger * Only emit warning when the action is really invalid [5cb9b41 | 2009-05-02 12:37:25 UTC] Michael Fellinger * Put the require of find into innate.rb [89d5858 | 2009-05-02 21:24:30 UTC] Andreas Karlsson * Simplify copy_variables by not using eval. Copying to an instance instead of a binding simplifies the code while also giving a minor performance enhancement as a bonus. Signed-off-by: Michael Fellinger [d1fe1f4 | 2009-05-02 21:38:28 UTC] Michael Fellinger * copy thread variables in Innate::defer [83d0a93 | 2009-05-02 20:59:52 UTC] Michael Fellinger * Remove Innate::STATE [f9ff691 | 2009-05-02 03:04:20 UTC] Andreas Karlsson * Move require due to profiling results. When profiling with ruby-prof it was reveiled to me that a major part of the time was spent inside require. Benchmarking with a simple hello world application revealed it to be about 25 percent faster without this require. Signed-off-by: Michael Fellinger [4155ea9 | 2009-05-01 22:51:53 UTC] Michael Fellinger * Only warn if we encounter an invalid action in render_custom, try to render still [b4a9e70 | 2009-05-01 22:46:49 UTC] Michael Fellinger * Be compatible with rack-test [3db47bc | 2009-05-01 22:46:38 UTC] Michael Fellinger * Be compatible with 1.8 [b3fb7be | 2009-05-01 21:07:10 UTC] Pistos * In render helper: render_template -> render_file . Changed relevant specs, too. Signed-off-by: Michael Fellinger [f3491f7 | 2009-04-30 11:59:16 UTC] Tadahiko Uehara * Skip template/view/layout lookup if the given path doesn't exist. Signed-off-by: Michael Fellinger [e4b5388 | 2009-05-01 15:30:31 UTC] Michael Fellinger * We don't want to call Innate::setup_dependencies for rendering... [7c90ec0 | 2009-05-01 14:22:29 UTC] Michael Fellinger * Default layout mapping to '/' [64517b3 | 2009-05-01 14:20:24 UTC] Michael Fellinger * Add some example invocations to the Helper::Render methods [d531f58 | 2009-05-01 14:19:39 UTC] Michael Fellinger * Adding Helper::Render#render_template due to popular demand [59229dc | 2009-05-01 13:18:39 UTC] Michael Fellinger * Speed up and simplify Etanni a little bit more [d8c3ca5 | 2009-04-30 16:07:12 UTC] Michael Fellinger * Add option to switch caching of compiled templates [21c4dfd | 2009-04-30 15:19:24 UTC] Michael Fellinger * Make Etanni a little bit more compact [43f6d76 | 2009-04-30 15:19:07 UTC] Michael Fellinger * First cut of template compilation, it's dumb, but it should speed things up a little [cca6d4d | 2009-04-29 21:34:45 UTC] Michael Fellinger * Improve the ColorFormatter, output background as well [abda94c | 2009-04-29 18:04:43 UTC] Michael Fellinger * Only add :trigger to options if there is one [559e711 | 2009-04-29 14:51:58 UTC] Michael Fellinger * Spec cookie setting before redirect. Closes #1 [9c85a49 | 2009-04-28 20:05:33 UTC] Michael Fellinger * Make the template lookup work without globs, hopefully that works on GAE now [a0b1f4a | 2009-04-28 19:41:40 UTC] Michael Fellinger * Make helper lookup work without glob [49ed57b | 2009-04-28 19:41:28 UTC] Michael Fellinger * Tell people that routing static files doesn't work [ff310ab | 2009-04-23 22:30:05 UTC] Michael Fellinger * Avoid issues with symbol comparision on 1.8 [fce62b9 | 2009-04-26 23:30:44 UTC] Michael Fellinger * Support setting multiple AOP hooks at once in before/after/wrap [ffd8edd | 2009-04-25 21:59:47 UTC] Michael Fellinger * Give innate a rubyforge project [cf62a9c | 2009-04-25 21:59:20 UTC] Michael Fellinger * Version 2009.04 [0ec2012 | 2009-04-23 13:21:17 UTC] Michael Fellinger * Allow deletion of mapped apps in DynaMap [cbedd9c | 2009-04-23 12:04:04 UTC] Ryan Grove * Add path and full_path to Innate::Action Signed-off-by: Michael Fellinger [b9a0d4b | 2009-04-20 12:12:29 UTC] Michael Fellinger * Make the u and h aliases for the CGI helper module_functions too [b68aad4 | 2009-04-20 12:12:10 UTC] Michael Fellinger * Allow further modification of the Action in the render_* methods via block [dca3531 | 2009-04-20 06:38:06 UTC] Ryan Grove * Preserve response headers when redirecting. Closes #1 Signed-off-by: Michael Fellinger [d465ca3 | 2009-04-18 09:46:09 UTC] Michael Fellinger * Version 2009.04.18 [987c5d7 | 2009-04-18 09:44:26 UTC] Michael Fellinger * Update the release tasks [f927c9d | 2009-04-17 18:51:35 UTC] Michael Fellinger * Add Content-Disposition support to send_file [888318c | 2009-04-17 17:43:10 UTC] Michael Fellinger * Better English in render_custom error [15078e6 | 2009-04-15 23:49:04 UTC] Michael Fellinger * Add comment about planned deprecation of SendFile helper's default status [4b487aa | 2009-04-15 23:48:09 UTC] Michael Fellinger * Remove the length from Response, Rack provides that [1634391 | 2009-04-15 18:02:11 UTC] Michael Fellinger * Don't camel-case the helper module name, simply remove underscores, we do case-insensitive lookup anyway [f97e8d7 | 2009-04-15 17:58:35 UTC] Michael Fellinger * Remove core_extensions, we don't need String#each or BasicObject anymore [0b33546 | 2009-04-15 16:16:24 UTC] Michael Fellinger * Action may be invalid if the node requires a method and view [39dd843 | 2009-04-15 16:15:30 UTC] Michael Fellinger * Escape non-hash arguments to Helper::Link#route (ryan grove) [22ee4df | 2009-04-15 14:25:02 UTC] Michael Fellinger * Raise if the Render helper cannot obtain an Action [e229299 | 2009-04-13 19:48:05 UTC] Michael Fellinger * Allow Action#call even if we are outside Current#wrap [b6e9558 | 2009-04-13 11:37:42 UTC] Michael Fellinger * Remove Action#exts member and use better terms [46d2a5e | 2009-04-12 12:03:58 UTC] Michael Fellinger * FileBased caches have access to @filename now [f84f18f | 2009-04-12 12:03:39 UTC] Michael Fellinger * Set a PROJECT_README for some rake tasks [8920482 | 2009-04-12 12:03:21 UTC] Michael Fellinger * Improvment and spec for provide example [a892dea | 2009-04-12 12:02:50 UTC] Michael Fellinger * Minor improvment and spec for retro games example [b3aeb97 | 2009-04-10 19:30:08 UTC] Michael Fellinger * Allow overriding of middleware mode for specs [7d65255 | 2009-04-10 19:07:15 UTC] Michael Fellinger * Compact code [cde9366 | 2009-04-10 17:51:03 UTC] Michael Fellinger * Simplify specs and make them pass using rack-test [f4c9572 | 2009-04-10 17:50:34 UTC] Michael Fellinger * Don't forget to specify an app for rack-test [41b1955 | 2009-04-10 17:17:42 UTC] Michael Fellinger * Remove spec for render_template [a3b73ca | 2009-04-10 17:17:27 UTC] Michael Fellinger * Add `rake setup` task to comply to convention. I will put up the corresponding gems ASAP [c648bf7 | 2009-04-10 17:16:12 UTC] Michael Fellinger * Switch to using rack-test for our specs, needs rack-test from the master branch head [5c08e25 | 2009-04-10 00:52:28 UTC] Michael Fellinger * Use ContentLength middleware [0dc50d4 | 2009-04-09 23:10:51 UTC] Michael Fellinger * Fix template caching... was using html instead of the wish the glob was for [622bbe3 | 2009-04-09 23:01:08 UTC] Michael Fellinger * Fix example apps [6e9e843 | 2009-04-07 16:56:56 UTC] Sam Carr * Minor tidy-ups to fix comments, add missing requires, add comments etc. Signed-off-by: Michael Fellinger [8f9af98 | 2009-04-08 01:42:35 UTC] Michael Fellinger * Set default interval for reloader to 2 seconds [9f7e749 | 2009-04-08 01:42:14 UTC] Michael Fellinger * Never assign $0, bad mojo [281501e | 2009-04-08 00:53:08 UTC] Michael Fellinger * Don't assign a directory to $0 [8a2ddc7 | 2009-04-08 00:16:37 UTC] Michael Fellinger * Version 2009.04.08 [89ab244 | 2009-04-07 23:17:07 UTC] Michael Fellinger * bring the retro_games example up to date [c1b6939 | 2009-04-07 21:30:14 UTC] Michael Fellinger * Fix typo in howto_spec example [c1f7bb8 | 2009-04-07 19:24:50 UTC] Michael Fellinger * Improve Helper::CGI, don't accept more than one argument per method [c01a0ce | 2009-04-07 09:07:28 UTC] Michael Fellinger * Warn if action is invalid [d749887 | 2009-04-07 09:07:01 UTC] Michael Fellinger * Remove Helper::Render#render_template [fba39b5 | 2009-04-06 10:26:29 UTC] Michael Fellinger * Remove specs for Helper::Partial [98bc6f7 | 2009-04-06 10:25:52 UTC] Michael Fellinger * Add more specs and refine Helper::Render [616b5aa | 2009-04-06 10:03:21 UTC] Michael Fellinger * Provide direct access to Helper::Render methods through extension [696f85d | 2009-04-06 09:58:09 UTC] Michael Fellinger * Make Helper::Render#render_template work and add specs [b0fcf13 | 2009-04-06 06:51:09 UTC] Michael Fellinger * Adding Helper::Render, this should be able to cover all our rendering needs [ea02bbe | 2009-04-06 06:49:52 UTC] Michael Fellinger * Remove Helper::Partial, to be replaced by Helper::Render [52c9943 | 2009-04-06 06:47:01 UTC] Michael Fellinger * just fix some annoying things [cd45648 | 2009-04-06 06:46:17 UTC] Michael Fellinger * Refactor Helper to use HelpersHelper.options [4a1b7f6 | 2009-04-05 21:25:43 UTC] Michael Fellinger * remove some more methods from Request, they depend on a method in ramaze [6e0b421 | 2009-04-05 16:22:19 UTC] Michael Fellinger * Make multipart building a bit more compact [2f17bf6 | 2009-04-05 21:23:45 UTC] Michael Fellinger * Make some variables more 'communicative', as reek puts it [348e179 | 2009-04-04 13:37:50 UTC] Michael Fellinger * Caching for template locations finally working, this should reduce the disk IO through globbing considerably, even if it is still updating the locations for every request [8555277 | 2009-04-04 13:27:54 UTC] Michael Fellinger * Better bacon task [110243b | 2009-04-03 19:08:41 UTC] Michael Fellinger * Experimental templating path caching [258d7c9 | 2009-04-03 20:01:12 UTC] Michael Fellinger * Use Etanni engine for specs and most examples [2bf8941 | 2009-04-03 19:59:56 UTC] Michael Fellinger * Comment out gemspec dependencies until rack is released [57078ac | 2009-04-03 19:58:24 UTC] Michael Fellinger * Remove the extra newlines introduced with Etanni [51b4797 | 2009-04-03 19:58:03 UTC] Michael Fellinger * Relax views by using #to_s instead of #to_str [d8475d3 | 2009-04-03 16:48:49 UTC] Michael Fellinger * Don't carry over view_value into layout actions [8e2788f | 2009-04-02 10:50:52 UTC] Michael Fellinger * Fix view and layout mapping if there are multiple view_mappings [8e93e87 | 2009-03-31 23:35:56 UTC] Michael Fellinger * Version 2009.04.01 [1a7242b | 2009-03-31 23:32:40 UTC] Michael Fellinger * Optional is called Optioned now, watch out [0809fb1 | 2009-03-31 14:50:46 UTC] Michael Fellinger * Set proper default templating engine for html to Etanni [e1f9450 | 2009-03-31 13:14:34 UTC] Michael Fellinger * Make sure Etanni returns stripped strings, that should make the specs pass again [3c7063b | 2009-03-31 12:49:02 UTC] Michael Fellinger * Fix bug where root_mappings where not considered alternatives [0ab5ab1 | 2009-03-29 20:44:26 UTC] Michael Fellinger * Unescape params given to the action [4fe8226 | 2009-03-28 16:04:30 UTC] Michael Fellinger * Version 2009.03.28 [57680d3 | 2009-03-28 16:04:16 UTC] Michael Fellinger * Split rake tasks into small units for management with raku [d7a9278 | 2009-03-26 21:14:30 UTC] Michael Fellinger * Adapt recursive partial spec for new action iv setting semantics [4dede34 | 2009-03-26 19:20:14 UTC] Michael Fellinger * Nicer code for Action#layout_view_or_method [d392fda | 2009-03-26 19:19:52 UTC] Michael Fellinger * Make Node#resolve smarter if called on an instance [3e49468 | 2009-03-26 18:40:30 UTC] Michael Fellinger * Put copy_variables before calling of the action method, so instance variables are copied over from the action and usable in the method the same way as in the template [408bbd9 | 2009-03-26 10:28:41 UTC] Michael Fellinger * Better lookup for options.roots [250188f | 2009-03-25 22:48:56 UTC] Michael Fellinger * Give the engine the value or a string, not nil [6784523 | 2009-03-25 22:37:34 UTC] Michael Fellinger * Adding Etanni with .xhtml extension [dc871bf | 2009-03-25 20:35:40 UTC] Michael Fellinger * Remove specs for old request methods [fa7aa95 | 2009-03-25 20:35:23 UTC] Michael Fellinger * Don't fail when trying to obtain symbolic view [a79b532 | 2009-03-25 20:34:59 UTC] Michael Fellinger * Allow Ramaze to inject Request/Response/Session [3799d36 | 2009-03-25 20:34:19 UTC] Michael Fellinger * Using Gem::Specification#to_ruby, yay [6367793 | 2009-03-25 17:01:07 UTC] Michael Fellinger * Remove cruft from View::ERB [72b02f0 | 2009-03-25 17:00:53 UTC] Michael Fellinger * Simplify View::get, we don't need lookup by extension anymore [b4850cd | 2009-03-25 17:00:05 UTC] Michael Fellinger * Remove some methods from Request, they fit better into Ramaze [d919c03 | 2009-03-25 16:59:36 UTC] Michael Fellinger * Remove cruft from Adapter, I added support for arbitrary handlers to rack (patch will go in by tomorrow) [b7a4f88 | 2009-03-25 13:01:24 UTC] Michael Fellinger * Remove some unused methods [afea731 | 2009-03-24 22:52:16 UTC] Michael Fellinger * Version 2009.03.24 [94d0714 | 2009-03-24 18:33:44 UTC] Michael Fellinger * Fix bug where index(arg) was passed 'index' as arg [28c9f16 | 2009-03-24 15:05:43 UTC] Michael Fellinger * Nicer output for skipped specs [ea90a79 | 2009-03-24 15:05:30 UTC] Michael Fellinger * Fix specs for 1.9 [404cffe | 2009-03-23 18:43:50 UTC] Michael Fellinger * Using anchor in combination with route would fail between nodes [b9c4048 | 2009-03-23 18:23:30 UTC] Michael Fellinger * Update README to reflect latest developments [bd4456e | 2009-03-23 14:53:56 UTC] Michael Fellinger * Copy action.variables into instance variables before calling engine [85b1b75 | 2009-03-23 14:27:16 UTC] Michael Fellinger * Only render_template if the resulting action is valid [1e9009c | 2009-03-23 14:03:16 UTC] Michael Fellinger * Make the methods in Helper::CGI module functions [3e20690 | 2009-03-21 10:36:52 UTC] Michael Fellinger * Fix outstanding issues around State and spec them [1906be4 | 2009-03-21 01:15:54 UTC] Michael Fellinger * Clean up a bit after suggestions from nitpick [e89cde5 | 2009-03-20 18:35:55 UTC] Michael Fellinger * Only set root in spec if found [45e1307 | 2009-03-20 18:34:51 UTC] Michael Fellinger * Add some aliases for options given to Innate.start, should make life easier [c418e85 | 2009-03-20 17:25:20 UTC] Michael Fellinger * Add specs for extended behaviour of Request#domain [17a1ca3 | 2009-03-20 17:24:44 UTC] Michael Fellinger * Support put/delete in shared :mock [f857946 | 2009-03-20 17:24:18 UTC] Michael Fellinger * Take advantage of new Rack::Request#url for Request#domain [b849861 | 2009-03-20 17:23:45 UTC] Michael Fellinger * small style change [a0d3176 | 2009-03-20 17:23:01 UTC] Michael Fellinger * Don't rescue anything in Helper, all exceptions get shown [3e5869d | 2009-03-19 20:57:08 UTC] Michael Fellinger * Remove unused method from node spec [27ffac3 | 2009-03-19 20:48:05 UTC] Michael Fellinger * Clean up and remove methods that aren't used anymore [1e09f3c | 2009-03-19 20:47:03 UTC] Michael Fellinger * Improve spec/helper.rb to work with rcov [ca75800 | 2009-03-19 20:46:40 UTC] Michael Fellinger * Fix logical typo [057b52e | 2009-03-19 20:12:56 UTC] Michael Fellinger * Spec Node mapping generation [05a244a | 2009-03-19 20:09:29 UTC] Michael Fellinger * Move node aspects into the aspect helper, make traits faster [f774349 | 2009-03-19 18:18:14 UTC] Michael Fellinger * Better session id, use securerandom if possible (ruby >= 1.8.7) [4b8d305 | 2009-03-19 17:58:57 UTC] Michael Fellinger * update_method_arities only once per request [3d7a493 | 2009-03-19 17:51:38 UTC] Michael Fellinger * Remove some debugging output [2650232 | 2009-03-19 17:51:16 UTC] Michael Fellinger * No need for next [b8e2c90 | 2009-03-18 19:49:33 UTC] Michael Fellinger * Run Innate.setup_dependencies for shared :mock [335c4d0 | 2009-03-18 19:49:09 UTC] Michael Fellinger * Forgot commiting the change to Node#root_mappings [e7a022c | 2009-03-18 19:48:08 UTC] Michael Fellinger * Node docs more compatible with YARD [8bab954 | 2009-03-18 19:37:57 UTC] Michael Fellinger * Adding Helper::Link#route_location, makes life easier for Ramaze [ce9a71d | 2009-03-18 19:35:55 UTC] Michael Fellinger * More intelligent automatic mapping [3227e0b | 2009-03-18 17:40:58 UTC] Michael Fellinger * Split up the specs for Node a little [176f1f8 | 2009-03-17 20:09:35 UTC] Michael Fellinger * And even more docs for Node [6992116 | 2009-03-17 19:43:01 UTC] Michael Fellinger * Update specs for new template lookup [68ba841 | 2009-03-17 19:41:35 UTC] Michael Fellinger * Add more docs, yard uses @example instead of @usage [45c7a24 | 2009-03-17 19:40:17 UTC] Michael Fellinger * Document some of the stuff that goes on in the Node#layout method, allow removing layout from node [fb36a5f | 2009-03-17 19:39:27 UTC] Michael Fellinger * Remove the Node#layout_root method [f2e4cc7 | 2009-03-17 19:38:15 UTC] Michael Fellinger * Use param as variable name for the options hash to avoid confusion [a457bdf | 2009-03-17 19:30:59 UTC] Michael Fellinger * Refactor Node options Node options are now done by traits. The reasoning behind this is that one wants to inherit options from nodes they subclass and that lookup of these options should be fast. Lookup of views is this: [Innate.options.roots, Innate.options.views, Node.trait[:views], name] Lookup of layouts is this: [Innate.options.roots, Innate.options.layouts, Node.trait[:layouts], name] If the traits are empty arrays, the Node.mapping is used instead. Setting a custom view or layout mapping works like: class Foo Innate.node('/') map_views '/foobar' map_layouts '/foobar' end More about this soon in the docs. [9b78d9c | 2009-03-17 19:28:35 UTC] Michael Fellinger * Fix the non-node references to Node.options [64cfecb | 2009-03-17 19:27:41 UTC] Michael Fellinger * Move some Node.options to Innate.options again, they make more sense there [f2db256 | 2009-03-16 15:00:03 UTC] Michael Fellinger * Handle nil in path_glob gracefully [1b2435b | 2009-03-16 14:38:56 UTC] Michael Fellinger * Even more docs for Node [c9dad64 | 2009-03-16 14:38:26 UTC] Michael Fellinger * Better information about ambigous templates [9fef72f | 2009-03-16 14:38:01 UTC] Michael Fellinger * Some more docs for Node [07230ee | 2009-03-16 13:53:43 UTC] Michael Fellinger * Simple example for provides [9fa53a0 | 2009-03-16 13:53:21 UTC] Michael Fellinger * Some docs for Node#provide [93ffd36 | 2009-03-16 09:58:20 UTC] Michael Fellinger * Add Innate::Helper::Link#route_self [89b5f05 | 2009-03-15 16:09:07 UTC] Michael Fellinger * Try setting $0 correctly in Innate.start [75fe61d | 2009-03-15 11:25:24 UTC] Michael Fellinger * Options of modules in Innate should be subs of Innate.options, not simple references [19797aa | 2009-03-14 21:38:01 UTC] Michael Fellinger * Proper fallback for Options#[]= [53e5412 | 2009-03-14 21:37:46 UTC] Michael Fellinger * Allow multiple public roots [88f6b82 | 2009-03-14 13:25:02 UTC] Michael Fellinger * The :app trait isn't needed anymore [f3b5d20 | 2009-03-14 13:18:09 UTC] Michael Fellinger * Add missing options/stub.rb [33c2fbe | 2009-03-14 13:17:51 UTC] Michael Fellinger * Allow to change the object wrapped by Rack::MockRequest [2e5eccf | 2009-03-14 13:12:43 UTC] Michael Fellinger * Refactor to use new options convention, each module has its own options now [b271865 | 2009-03-14 13:09:46 UTC] Michael Fellinger * Make specs easier by setting $0 correctly [346c8f3 | 2009-03-14 13:09:13 UTC] Michael Fellinger * More specs for Innate::Options [786a340 | 2009-03-14 13:08:02 UTC] Michael Fellinger * Improve Innate::Options and add Innate::Optional [5d84d92 | 2009-03-12 20:28:01 UTC] Michael Fellinger * Rewire to use Innate::MiddlewareCompiler and allow Ramaze to use its own URLMap [a4461b8 | 2009-03-12 20:26:58 UTC] Michael Fellinger * Fix Helper::Flash spec, we need to return a string [7d22edb | 2009-03-12 20:26:30 UTC] Michael Fellinger * Nicer debugging output for routing [12d63ac | 2009-03-12 18:23:00 UTC] Michael Fellinger * Dynamic MiddlewareCompiler, removes last Rack namespaced class [aa7e2e1 | 2009-03-09 19:09:51 UTC] Michael Fellinger * Move default hash into Action::create to prevent silly behaviour [68b8ec0 | 2009-03-07 14:48:51 UTC] Michael Fellinger * Refactor of content representation, should work smooth now [e1ade5a | 2009-03-06 14:42:20 UTC] Michael Fellinger * Improve Helper::Link#anchor on suggestions of endoh [d7ec2e6 | 2009-03-06 14:16:15 UTC] Michael Fellinger * Some explanation about session.expires [7b95de4 | 2009-03-06 14:15:36 UTC] Michael Fellinger * Refactor provides, any engine just has to respond to ::call now [e9302f0 | 2009-03-05 13:37:47 UTC] Michael Fellinger * Another change to template exts, only respect the wish to simplify things [5bc84c1 | 2009-03-05 12:19:54 UTC] Michael Fellinger * Remove our Rack::Reloader - i'll try to improve the one in Rack instead and Ramaze has its own anyway [3712cff | 2009-03-05 12:06:56 UTC] Michael Fellinger * Utilize application-specific configuration [527a29f | 2009-03-05 12:04:35 UTC] Michael Fellinger * Split up to_template with path_glob and ext_glob [66ea210 | 2009-03-04 15:53:53 UTC] Michael Fellinger * Allow multiple values for options.app.(root|view|layout|public) [671aaea | 2009-03-05 17:02:48 UTC] Michael Fellinger * View::register overwrites [663d623 | 2009-03-03 01:20:23 UTC] Michael Fellinger * Options is not Enumerable anymore, add to_hash instead [e30a191 | 2009-03-03 01:20:02 UTC] Michael Fellinger * simplify helper failure [c1328ed | 2009-03-02 16:13:53 UTC] Michael Fellinger * Use Options#[] for faster access and add Innate::teardown_dependencies [a56126b | 2009-03-02 16:13:15 UTC] Michael Fellinger * Fix middleware compilation [7d92080 | 2009-03-01 18:46:02 UTC] Tadahiko Uehara * Add spec for render_template with variable. [b5cdf83 | 2009-03-01 15:56:20 UTC] Tadahiko Uehara * Use Array#first instead of to_s to get extension from provide wish in Array#to_s in 1.9 joins with brackets. # ['foo'].to_s #=> "[\"foo\"]" [2e8bb64 | 2009-03-01 23:20:36 UTC] Michael Fellinger * Nicer exception for some missing helpers [a5de43a | 2009-03-01 23:20:16 UTC] Michael Fellinger * MiddlewareCompiler#use now has traditional rack meaning, use apps for the old behaviour [aedca0f | 2009-03-01 23:19:27 UTC] Michael Fellinger * Use options[:mode] to avoid problems with facets [f17eec8 | 2009-03-01 15:02:13 UTC] Michael Fellinger * Add Innate::defer to schedule code for running in background [b7e58fa | 2009-02-28 16:12:02 UTC] Michael Fellinger * Simplify view API a bit [37a05e8 | 2009-02-25 15:04:52 UTC] Michael Fellinger * Fix version for rack in gemspec [e29cd02 | 2009-02-25 15:03:20 UTC] Michael Fellinger * innate doesn't rely on github [08d6773 | 2009-02-25 15:01:07 UTC] Michael Fellinger * Version 2009.02.25 [04201ef | 2009-02-25 14:27:15 UTC] Michael Fellinger * cleanup [295a241 | 2009-02-25 14:27:10 UTC] Michael Fellinger * Add Traited#class_trait and docs [6ed8499 | 2009-02-25 14:04:24 UTC] Michael Fellinger * rebuild middleware if block is passed to Innate.start [8ce86a7 | 2009-02-25 14:04:01 UTC] Michael Fellinger * Make the real failures on helper requires visible [232214e | 2009-02-25 14:03:29 UTC] Michael Fellinger * Remove optimization for wrap_action_call, leads to really weird recursion [38d0a7b | 2009-02-25 13:09:53 UTC] Michael Fellinger * Simplify setting of mode and compilation of middleware [8c02417 | 2009-02-25 12:40:11 UTC] Michael Fellinger * Speed up wrap_action_call [cea8af5 | 2009-02-25 12:37:29 UTC] Michael Fellinger * Speed up ancestral_trait [608a7eb | 2009-02-24 21:45:15 UTC] Michael Fellinger * Remove Innate::Setup, that goes into Ramaze [785b1e5 | 2009-02-24 21:45:04 UTC] Michael Fellinger * Remove reference to Innate in log to avoid confusion [3df0612 | 2009-02-24 21:28:02 UTC] Michael Fellinger * Remove the providing_hash example until we come up with a better way to show it [8309299 | 2009-02-24 21:25:36 UTC] Michael Fellinger * small cleanup [93be7ad | 2009-02-24 21:25:25 UTC] Michael Fellinger * Spec the session example [7b39146 | 2009-02-24 21:24:45 UTC] Michael Fellinger * Add missing template for node spec [d8ccfce | 2009-02-24 21:22:56 UTC] Michael Fellinger * Add todolist example [fd73cef | 2009-02-24 21:06:01 UTC] Michael Fellinger * Don't serve a view without method if params are given [58f9ecd | 2009-02-24 20:05:27 UTC] Michael Fellinger * Fix spec for example/link [607fc72 | 2009-02-24 20:05:16 UTC] Michael Fellinger * Provide shared multipart to enable easy POST specs [9b833f8 | 2009-02-24 20:04:48 UTC] Michael Fellinger * Innate::Node, rename LIST to NODE_LIST and HELPERS to DEFAULT_HELPERS [397cff4 | 2009-02-24 20:03:38 UTC] Michael Fellinger * A little bit nicer each in retro games [0ab5dfe | 2009-02-24 19:09:07 UTC] Michael Fellinger * We don't provide error handling out of the box, remove example [9466549 | 2009-02-24 19:06:39 UTC] Michael Fellinger * Clean up code of the whywiki [715371b | 2009-02-24 18:58:44 UTC] Michael Fellinger * Bring examples up to date [378977c | 2009-02-22 21:14:09 UTC] Michael Fellinger * Add some docs [566303c | 2009-02-22 20:34:48 UTC] Michael Fellinger * Make Innate::setup and Innate::sync available to Ramaze [6fa8645 | 2009-02-22 20:16:33 UTC] Michael Fellinger * Make it easier for Ramaze to set a default engine [dfe34cd | 2009-02-21 20:54:34 UTC] Michael Fellinger * Correct usage of git tag [42d3883 | 2009-02-21 11:28:29 UTC] Michael Fellinger * Version 2009.02.21 [374f218 | 2009-02-21 11:26:55 UTC] Michael Fellinger * Bring retro games example back to life [800c1e2 | 2009-02-20 16:38:32 UTC] Michael Fellinger * Make Innate::Route() and Innate::Rewrite() available for Ramaze [f9d5d68 | 2009-02-20 14:48:24 UTC] Michael Fellinger * Don't fail fatal if no app root can be found [ddd6e77 | 2009-02-20 14:48:04 UTC] Michael Fellinger * Rename action_not_found(path) to action_missing(path), easier to remember [e682e18 | 2009-02-20 14:47:34 UTC] Michael Fellinger * Add trigger for options.mode to reset middleware [0efafb9 | 2009-02-19 16:29:04 UTC] Michael Fellinger * Update options spec for trigger [f3741ee | 2009-02-19 16:26:27 UTC] Michael Fellinger * Fix MiddlewareCompiler#static and add #directory [0ce72dc | 2009-02-19 16:07:33 UTC] Michael Fellinger * Put the dynamap module functions into the SingletonMethods so Ramaze can have them too [b392fa7 | 2009-02-19 16:06:36 UTC] Michael Fellinger * Add options.app.public which recompiles middleware on change [e9d3e04 | 2009-02-19 16:06:02 UTC] Michael Fellinger * Add Options#trigger, runs a block when an option changed [a3bdfdc | 2009-02-19 14:56:38 UTC] Michael Fellinger * Proper name for node in session spec [bc942f2 | 2009-02-19 14:52:37 UTC] Michael Fellinger * Some more yard-compatible docs [9f97f72 | 2009-02-19 14:16:03 UTC] Michael Fellinger * Make aliasing views more consistent [3d10ef2 | 2009-02-19 13:40:13 UTC] Michael Fellinger * Clean up session spec [027f20b | 2009-02-19 13:38:15 UTC] Michael Fellinger * Cache the session just as long as the cookie is scheduled to exist [0279f91 | 2009-02-19 13:37:17 UTC] Michael Fellinger * Further improvments to the spec task [f69b4cf | 2009-02-17 02:50:37 UTC] Michael Fellinger * publish for real [81048fa | 2009-02-17 02:48:51 UTC] Michael Fellinger * add rake publish via grancher [c825e8b | 2009-02-15 19:29:02 UTC] Tadahiko Uehara * Use current node's extension if it is not provided to render_template. [4338891 | 2009-02-15 19:29:02 UTC] Tadahiko Uehara * Use current node's extension if it is not provided to render_template. [e97696f | 2009-02-15 09:05:42 UTC] Michael Fellinger * Warn if no app.root was set Signed-off-by: Tadahiko Uehara [70f09fd | 2009-02-14 23:08:44 UTC] Tadahiko Uehara * Clear layout before rendering a template in #render_template. [4318c09 | 2009-02-15 10:05:42 UTC] Michael Fellinger * Warn if no app.root was set [22a7a1d | 2009-02-14 23:08:44 UTC] Tadahiko Uehara * Clear layout before rendering a template in #render_template. [4a31e76 | 2009-02-13 17:02:35 UTC] Michael Fellinger * Reflect change to Fiber from Ramaze [59ad732 | 2009-02-11 17:09:10 UTC] Michael Fellinger * Add bacon dependency for spec Signed-off-by: Tadahiko Uehara [d93b2e5 | 2009-02-11 17:15:55 UTC] Michael Fellinger * exit status 1 if specs fail Signed-off-by: Tadahiko Uehara [89327f5 | 2009-02-11 17:11:49 UTC] Michael Fellinger * Remove debug info, seems to work on RunCodeRun now Signed-off-by: Tadahiko Uehara [529f7e7 | 2009-02-11 16:50:11 UTC] Michael Fellinger * Install dependencies on for specs Signed-off-by: Tadahiko Uehara [da3fb06 | 2009-02-11 17:33:06 UTC] Michael Fellinger * Use eval with binding argument, Binding#eval is 1.8.7+ Signed-off-by: Tadahiko Uehara [7be640a | 2009-02-11 17:07:42 UTC] Michael Fellinger * debug RunCodeRun Signed-off-by: Tadahiko Uehara [c422ae6 | 2009-02-11 16:50:30 UTC] Michael Fellinger * Support for multiple extensions per engine Signed-off-by: Tadahiko Uehara [2cae45a | 2009-02-11 14:44:11 UTC] Michael Fellinger * Add options.app.prefix - only outbound for now Signed-off-by: Tadahiko Uehara [dcbdfdb | 2009-02-11 14:43:25 UTC] Michael Fellinger * Add rake ydoc task Signed-off-by: Tadahiko Uehara [3715913 | 2009-02-11 18:33:06 UTC] Michael Fellinger * Use eval with binding argument, Binding#eval is 1.8.7+ [eb77842 | 2009-02-11 18:15:55 UTC] Michael Fellinger * exit status 1 if specs fail [544533d | 2009-02-11 18:11:49 UTC] Michael Fellinger * Remove debug info, seems to work on RunCodeRun now [29d7021 | 2009-02-11 18:09:10 UTC] Michael Fellinger * Add bacon dependency for spec [d4ca17d | 2009-02-11 18:07:42 UTC] Michael Fellinger * debug RunCodeRun [8756390 | 2009-02-11 17:50:30 UTC] Michael Fellinger * Support for multiple extensions per engine [d5c003d | 2009-02-11 17:50:11 UTC] Michael Fellinger * Install dependencies on for specs [35f2ece | 2009-02-11 15:44:11 UTC] Michael Fellinger * Add options.app.prefix - only outbound for now [d212cd2 | 2009-02-11 15:43:25 UTC] Michael Fellinger * Add rake ydoc task [5210279 | 2009-02-09 16:47:15 UTC] Michael Fellinger * params defaults to [] Signed-off-by: Tadahiko Uehara [53cf3b0 | 2009-02-09 16:47:06 UTC] Michael Fellinger * Fix render_template Signed-off-by: Tadahiko Uehara [b8abf58 | 2009-02-09 16:37:08 UTC] Michael Fellinger * Cosmetics Signed-off-by: Tadahiko Uehara [b25f9e7 | 2009-02-09 16:36:50 UTC] Michael Fellinger * Some more usage of Innate::node Signed-off-by: Tadahiko Uehara [ad4f3ff | 2009-02-09 16:15:14 UTC] Michael Fellinger * Add convenience method Innate::node Signed-off-by: Tadahiko Uehara [d713321 | 2009-02-09 15:42:33 UTC] Michael Fellinger * Allow alias_view to point to another Node Signed-off-by: Tadahiko Uehara [af92ee4 | 2009-02-09 15:15:45 UTC] Michael Fellinger * Allow templates for methods like this__nested__one Signed-off-by: Tadahiko Uehara [56f119e | 2009-02-09 15:15:10 UTC] Michael Fellinger * Add options.action.needs_method Signed-off-by: Tadahiko Uehara [3cc7b5c | 2009-02-09 15:00:49 UTC] Michael Fellinger * Adapt specs for new API (memcached returns no value on delete) Signed-off-by: Tadahiko Uehara [3698234 | 2009-02-09 15:00:16 UTC] Michael Fellinger * Action is made a bit more modular so one can call Action#render Signed-off-by: Tadahiko Uehara [27520cb | 2009-02-08 14:51:37 UTC] Michael Fellinger * Correct behaviour for alias_view with spec Signed-off-by: Tadahiko Uehara [e5fcc9b | 2009-02-08 14:42:04 UTC] Michael Fellinger * Adapt node spec to new behaviour Signed-off-by: Tadahiko Uehara [487acde | 2009-02-08 14:41:50 UTC] Michael Fellinger * Fix alias_view, still needs spec Signed-off-by: Tadahiko Uehara [34269db | 2009-02-08 14:35:59 UTC] Michael Fellinger * Fix update_method_arities for new traits Signed-off-by: Tadahiko Uehara [030c75b | 2009-02-08 14:35:41 UTC] Michael Fellinger * Better error message if no action was found Signed-off-by: Tadahiko Uehara [8e5b4dd | 2009-02-08 13:42:04 UTC] Michael Fellinger * Restructure innate.rb and introduce options.mode Signed-off-by: Tadahiko Uehara [6524d1c | 2009-02-08 13:41:29 UTC] Michael Fellinger * Fix trait memory-leak Signed-off-by: Tadahiko Uehara [82673cd | 2009-02-09 17:47:15 UTC] Michael Fellinger * params defaults to [] [fe17b8d | 2009-02-09 17:47:06 UTC] Michael Fellinger * Fix render_template [9d23d82 | 2009-02-09 17:37:08 UTC] Michael Fellinger * Cosmetics [e6b6d79 | 2009-02-09 17:36:50 UTC] Michael Fellinger * Some more usage of Innate::node [da464b9 | 2009-02-09 17:15:14 UTC] Michael Fellinger * Add convenience method Innate::node [ed2bdee | 2009-02-09 16:42:33 UTC] Michael Fellinger * Allow alias_view to point to another Node [95238a3 | 2009-02-09 16:15:45 UTC] Michael Fellinger * Allow templates for methods like this__nested__one [fc75dca | 2009-02-09 16:15:10 UTC] Michael Fellinger * Add options.action.needs_method [190e66b | 2009-02-09 16:00:49 UTC] Michael Fellinger * Adapt specs for new API (memcached returns no value on delete) [68ad412 | 2009-02-09 16:00:16 UTC] Michael Fellinger * Action is made a bit more modular so one can call Action#render [4818105 | 2009-02-08 15:51:37 UTC] Michael Fellinger * Correct behaviour for alias_view with spec [ffee12e | 2009-02-08 15:42:04 UTC] Michael Fellinger * Adapt node spec to new behaviour [2034ce4 | 2009-02-08 15:41:50 UTC] Michael Fellinger * Fix alias_view, still needs spec [2778db9 | 2009-02-08 15:35:59 UTC] Michael Fellinger * Fix update_method_arities for new traits [faae0e0 | 2009-02-08 15:35:41 UTC] Michael Fellinger * Better error message if no action was found [ca68ade | 2009-02-08 14:42:04 UTC] Michael Fellinger * Restructure innate.rb and introduce options.mode [228951a | 2009-02-08 14:41:29 UTC] Michael Fellinger * Fix trait memory-leak [fb91811 | 2009-02-07 16:20:22 UTC] Michael Fellinger * Remove unused actions in Helper::Flash spec Signed-off-by: Tadahiko Uehara [4205f14 | 2009-02-07 16:13:13 UTC] Michael Fellinger * Fix usage of parameters in accept_language Signed-off-by: Tadahiko Uehara [bf69983 | 2009-02-07 16:11:37 UTC] Michael Fellinger * Specs for layouts Signed-off-by: Tadahiko Uehara [256c8c9 | 2009-02-07 16:11:09 UTC] Michael Fellinger * New layout behaviour Signed-off-by: Tadahiko Uehara [d78cedb | 2009-02-07 14:58:19 UTC] Michael Fellinger * Allow adding multiple caches at once Signed-off-by: Tadahiko Uehara [ff74c88 | 2009-02-07 14:58:04 UTC] Michael Fellinger * wrap_action_call hooks should return the body Signed-off-by: Tadahiko Uehara [0b34ab6 | 2009-02-07 11:57:23 UTC] Michael Fellinger * Better parsing of Request#accept_language Signed-off-by: Tadahiko Uehara [bff2472 | 2009-02-07 11:56:53 UTC] Michael Fellinger * Faster Innate.options Signed-off-by: Tadahiko Uehara [532f3a2 | 2009-02-06 16:44:46 UTC] Michael Fellinger * Minor fixes and docs for rakefile Signed-off-by: Tadahiko Uehara [345157b | 2009-02-06 16:44:33 UTC] Michael Fellinger * Provide default for alias_view Signed-off-by: Tadahiko Uehara [febab0f | 2009-02-06 16:41:34 UTC] Michael Fellinger * Version 2009.02.06 Signed-off-by: Tadahiko Uehara [3ed0607 | 2009-02-07 17:20:22 UTC] Michael Fellinger * Remove unused actions in Helper::Flash spec [e80d217 | 2009-02-07 17:13:13 UTC] Michael Fellinger * Fix usage of parameters in accept_language [3f5adb8 | 2009-02-07 17:11:37 UTC] Michael Fellinger * Specs for layouts [f2bdd45 | 2009-02-07 17:11:09 UTC] Michael Fellinger * New layout behaviour [e9c6ae3 | 2009-02-07 15:58:19 UTC] Michael Fellinger * Allow adding multiple caches at once [defd5aa | 2009-02-07 15:58:04 UTC] Michael Fellinger * wrap_action_call hooks should return the body [6d20f61 | 2009-02-07 12:57:23 UTC] Michael Fellinger * Better parsing of Request#accept_language [00ed695 | 2009-02-07 12:56:53 UTC] Michael Fellinger * Faster Innate.options [ec09fde | 2009-02-06 17:44:46 UTC] Michael Fellinger * Minor fixes and docs for rakefile [45497a2 | 2009-02-06 17:44:33 UTC] Michael Fellinger * Provide default for alias_view [1dd1d29 | 2009-02-06 17:41:34 UTC] Michael Fellinger * Version 2009.02.06 [01ca014 | 2009-02-04 01:37:50 UTC] Tadahiko Uehara * Delete :root and :file parameters after root is figured. Because they Signed-off-by: Michael Fellinger [caf7b61 | 2009-02-04 01:32:01 UTC] Tadahiko Uehara * Add Action#name, taken from Ramaze. Signed-off-by: Michael Fellinger [d10e1e4 | 2009-02-04 02:37:50 UTC] Tadahiko Uehara * Delete :root and :file parameters after root is figured. Because they [a0eaff1 | 2009-02-04 02:32:01 UTC] Tadahiko Uehara * Add Action#name, taken from Ramaze. [f83a30c | 2009-02-01 14:50:02 UTC] Michael Fellinger * Rack now has nested parameter parsing Signed-off-by: Tadahiko Uehara [cc3f110 | 2009-02-02 02:35:42 UTC] Tadahiko Uehara * use view name as name of the method when method is unavailable. [20518d4 | 2009-02-02 02:37:47 UTC] Tadahiko Uehara * update aspect spec to check before/after_all, instance_eval and view without method. [ad974e8 | 2009-02-02 12:28:20 UTC] Michael Fellinger * instance_eval the aspect blocks [12460ae | 2009-02-02 02:37:47 UTC] Tadahiko Uehara * update aspect spec to check before/after_all, instance_eval and view without method. [ac3cd91 | 2009-02-02 02:35:42 UTC] Tadahiko Uehara * use view name as name of the method when method is unavailable. [1ac84ef | 2009-02-02 02:32:14 UTC] Tadahiko Uehara * instance_eval the aspect block. [2287f32 | 2009-02-02 02:31:17 UTC] Tadahiko Uehara * block_holder can be a hash or an actual block. lets first check it. [b180b45 | 2009-02-01 15:50:02 UTC] Michael Fellinger * Rack now has nested parameter parsing [71639b6 | 2009-01-31 19:45:28 UTC] Michael Fellinger * Some yard-style docs Signed-off-by: Tadahiko Uehara [6b70d31 | 2009-01-31 19:45:37 UTC] Michael Fellinger * Remove useless adapters Signed-off-by: Tadahiko Uehara [50b78b5 | 2009-01-31 19:45:03 UTC] Michael Fellinger * Make Node#wrap_action_call work, for now only aspects are registered Signed-off-by: Tadahiko Uehara [2a827d7 | 2009-01-31 19:43:57 UTC] Michael Fellinger * Improve Action#copy_variables Signed-off-by: Tadahiko Uehara [4ae1a01 | 2009-01-31 20:45:37 UTC] Michael Fellinger * Remove useless adapters [f75e32d | 2009-01-31 20:45:28 UTC] Michael Fellinger * Some yard-style docs [a7c4120 | 2009-01-31 20:45:03 UTC] Michael Fellinger * Make Node#wrap_action_call work, for now only aspects are registered [46c35c0 | 2009-01-31 20:43:57 UTC] Michael Fellinger * Improve Action#copy_variables [b7595b3 | 2009-01-30 18:12:09 UTC] Michael Fellinger * Fix assignment for (before|after)_all Signed-off-by: Tadahiko Uehara [76e1be6 | 2009-01-30 19:48:17 UTC] Tadahiko Uehara * Fixed forgotten merge portion in previous 5de42ee51db98a4ca211a4513056f47389904420. [7076383 | 2009-01-30 19:12:09 UTC] Michael Fellinger * Fix assignment for (before|after)_all [3e9a5a8 | 2009-01-30 17:57:19 UTC] Michael Fellinger * Add before_all/after_all aspects Signed-off-by: Tadahiko Uehara [1335bf2 | 2009-01-30 18:57:19 UTC] Michael Fellinger * Add before_all/after_all aspects [8b57671 | 2009-01-29 22:21:51 UTC] Michael Fellinger * trap only once Signed-off-by: Tadahiko Uehara [9e56624 | 2009-01-29 20:37:23 UTC] Michael Fellinger * method_arities is a trait now Signed-off-by: Tadahiko Uehara [82646b1 | 2009-01-29 20:39:27 UTC] Michael Fellinger * Improve Node::setup, automap is now mapping and behaves like ramaze needs it Signed-off-by: Tadahiko Uehara [97e8308 | 2009-01-29 20:38:36 UTC] Michael Fellinger * Better naming and arguments for Adapter::start Signed-off-by: Tadahiko Uehara [b182882 | 2009-01-29 20:38:14 UTC] Michael Fellinger * Even if started is true, still do basic setup Signed-off-by: Tadahiko Uehara [e3ffd52 | 2009-01-29 20:37:46 UTC] Michael Fellinger * Don't use custom adapter in example Signed-off-by: Tadahiko Uehara [5d95198 | 2009-01-29 20:08:57 UTC] Michael Fellinger * Fix precedence issue in find_method Signed-off-by: Tadahiko Uehara [64d317f | 2009-01-29 18:04:14 UTC] Michael Fellinger * Remove requires for rubygems Signed-off-by: Tadahiko Uehara [508edc9 | 2009-01-29 18:02:19 UTC] Michael Fellinger * Remove whywiki_haml/whywiki_nagoro examples Signed-off-by: Tadahiko Uehara [b55cf95 | 2009-01-29 23:21:51 UTC] Michael Fellinger * trap only once [4d1eda4 | 2009-01-29 21:57:54 UTC] Tadahiko Uehara * Remove leftover code from previous addition. [b41c42a | 2009-01-29 21:39:57 UTC] Michael Fellinger * Work around issue in Rack::URLMap and add spec [9dde517 | 2009-01-29 21:39:27 UTC] Michael Fellinger * Improve Node::setup, automap is now mapping and behaves like ramaze needs it [861ef4d | 2009-01-29 21:38:36 UTC] Michael Fellinger * Better naming and arguments for Adapter::start [456c144 | 2009-01-29 21:38:14 UTC] Michael Fellinger * Even if started is true, still do basic setup [76e4b23 | 2009-01-29 21:37:46 UTC] Michael Fellinger * Don't use custom adapter in example [6921322 | 2009-01-29 21:37:23 UTC] Michael Fellinger * method_arities is a trait now [f66c001 | 2009-01-29 21:25:41 UTC] Tadahiko Uehara * Add layout spec and some more. [3dab943 | 2009-01-29 21:08:57 UTC] Michael Fellinger * Fix precedence issue in find_method [be40b43 | 2009-01-29 19:04:14 UTC] Michael Fellinger * Remove requires for rubygems [21d17f3 | 2009-01-29 19:02:19 UTC] Michael Fellinger * Remove whywiki_haml/whywiki_nagoro examples [03c14eb | 2009-01-28 18:55:46 UTC] Michael Fellinger * Move code for copying Action#variables Signed-off-by: Tadahiko Uehara [1084897 | 2009-01-28 21:38:29 UTC] Michael Fellinger * Fix cache specs, why the hell did they pass? Signed-off-by: Tadahiko Uehara [1968cb7 | 2009-01-28 20:55:35 UTC] Michael Fellinger * Add some specs for examples Signed-off-by: Tadahiko Uehara [9285cec | 2009-01-28 18:56:31 UTC] Michael Fellinger * Add Node::HELPERS for helpers used on inclusion Signed-off-by: Tadahiko Uehara [e6b9002 | 2009-01-28 19:04:20 UTC] Michael Fellinger * Remove require for route_exceptions Signed-off-by: Tadahiko Uehara [7b98be1 | 2009-01-28 18:55:25 UTC] Michael Fellinger * Rack::RouteExceptions is now in rack-contrib Signed-off-by: Tadahiko Uehara [e83fc84 | 2009-01-27 20:41:26 UTC] Michael Fellinger * Nicer inspect of session Signed-off-by: Tadahiko Uehara [6b0be6f | 2009-01-27 20:41:17 UTC] Michael Fellinger * Set cookie on the response object returned, not the original one Signed-off-by: Tadahiko Uehara [5b2403c | 2009-01-27 19:49:59 UTC] Michael Fellinger * Fix specs for 1.9 Signed-off-by: Tadahiko Uehara [36dbcc0 | 2009-01-27 19:49:10 UTC] Michael Fellinger * 1.9 will return symbols instead of strings as method names Signed-off-by: Tadahiko Uehara [9e5520e | 2009-01-27 19:48:48 UTC] Michael Fellinger * A bit nicer code style Signed-off-by: Tadahiko Uehara [eb0935f | 2009-01-27 19:48:25 UTC] Michael Fellinger * Map casts to #to_s, :/ is very common in ramaze code Signed-off-by: Tadahiko Uehara [580673b | 2009-01-27 19:47:53 UTC] Michael Fellinger * Fix handling of binding for 1.9 Signed-off-by: Tadahiko Uehara [f67b9a0 | 2009-01-27 19:46:45 UTC] Michael Fellinger * In current 1.9 the original require won't work for some gems Signed-off-by: Tadahiko Uehara [9133eb2 | 2009-01-28 22:38:29 UTC] Michael Fellinger * Fix cache specs, why the hell did they pass? [741a79c | 2009-01-28 21:55:35 UTC] Michael Fellinger * Add some specs for examples [122c35f | 2009-01-28 20:04:20 UTC] Michael Fellinger * Remove require for route_exceptions [2405c23 | 2009-01-28 19:56:31 UTC] Michael Fellinger * Add Node::HELPERS for helpers used on inclusion [94cde03 | 2009-01-28 19:55:46 UTC] Michael Fellinger * Move code for copying Action#variables [4452766 | 2009-01-28 19:55:25 UTC] Michael Fellinger * Rack::RouteExceptions is now in rack-contrib [2922c7b | 2009-01-28 20:44:43 UTC] Tadahiko Uehara * Add some specs. Signed-off-by: Michael Fellinger [cfc74b8 | 2009-01-28 20:43:50 UTC] Tadahiko Uehara * Add missing fallback argument to redirect_referrer. Signed-off-by: Michael Fellinger [e4534e1 | 2009-01-27 16:37:21 UTC] Tadahiko Uehara * Fix typo in example. Signed-off-by: Michael Fellinger [53b7764 | 2009-01-28 21:44:43 UTC] Tadahiko Uehara * Add some specs. [35b3fe7 | 2009-01-28 21:43:50 UTC] Tadahiko Uehara * Add missing fallback argument to redirect_referrer. [eeffc7d | 2009-01-27 21:41:26 UTC] Michael Fellinger * Nicer inspect of session [1daeb8f | 2009-01-27 21:41:17 UTC] Michael Fellinger * Set cookie on the response object returned, not the original one [c7f8f10 | 2009-01-27 20:49:59 UTC] Michael Fellinger * Fix specs for 1.9 [9075cff | 2009-01-27 20:49:10 UTC] Michael Fellinger * 1.9 will return symbols instead of strings as method names [fdd2197 | 2009-01-27 20:48:48 UTC] Michael Fellinger * A bit nicer code style [a2003fe | 2009-01-27 20:48:25 UTC] Michael Fellinger * Map casts to #to_s, :/ is very common in ramaze code [06331c4 | 2009-01-27 20:47:53 UTC] Michael Fellinger * Fix handling of binding for 1.9 [e7070f2 | 2009-01-27 20:46:45 UTC] Michael Fellinger * In current 1.9 the original require won't work for some gems [047baef | 2009-01-27 17:37:21 UTC] Tadahiko Uehara * Fix typo in example. [d3304dd | 2009-01-27 00:50:25 UTC] Michael Fellinger * pass arguments to start to start! [8f37866 | 2009-01-26 15:47:22 UTC] Michael Fellinger * Prettier output for rake spec [602c6c1 | 2009-01-26 15:42:33 UTC] Michael Fellinger * spec for provide json and layout [725f209 | 2009-01-26 15:42:13 UTC] Michael Fellinger * Fix layout render [c71fca2 | 2009-01-26 14:41:21 UTC] Michael Fellinger * Remove Content-Type before dispatch, only add if not set [07547ba | 2009-01-25 17:09:01 UTC] Michael Fellinger * add options.action.wish for higher order control over wishes [8394dc5 | 2009-01-25 17:08:38 UTC] Michael Fellinger * small fixes for options [aa53722 | 2009-01-24 13:05:37 UTC] Michael Fellinger * Expand specs for options [67f124d | 2009-01-24 13:05:24 UTC] Michael Fellinger * Expand specs for flash [e28bcda | 2009-01-24 13:05:04 UTC] Michael Fellinger * Fix Flash#delete [a78085c | 2009-01-24 13:04:46 UTC] Michael Fellinger * Prune never reached code from options dsl [dd778ba | 2009-01-24 13:04:18 UTC] Michael Fellinger * Docs for Helper::Link#route [3013397 | 2009-01-24 13:03:42 UTC] Michael Fellinger * Provide Innate::start! method [bdfe9da | 2009-01-24 13:03:24 UTC] Michael Fellinger * Ignore adapter for coverage [2484dd4 | 2009-01-24 11:34:36 UTC] Michael Fellinger * Innate::Helper::Link#route defaults to '/' [1e68525 | 2009-01-24 11:34:19 UTC] Michael Fellinger * Spec Innate::Helper::Link [8d988f0 | 2009-01-24 00:58:56 UTC] Michael Fellinger * Add clean task [ce74581 | 2009-01-23 23:53:00 UTC] Michael Fellinger * Spec Innate::Helper::CGI [6823756 | 2009-01-23 23:52:19 UTC] Michael Fellinger * Spec Innate::Helper::Partial [27fa85a | 2009-01-23 23:52:02 UTC] Michael Fellinger * Add specs for DynaMap [8e1ee7d | 2009-01-23 23:51:46 UTC] Michael Fellinger * Spec more of Request [766023a | 2009-01-23 23:51:29 UTC] Michael Fellinger * Expand redirect spec [66229fc | 2009-01-23 23:51:07 UTC] Michael Fellinger * Use shared mock a bit [6e62527 | 2009-01-23 23:50:39 UTC] Michael Fellinger * Spec that helper methods are no actions by default [b5dd53b | 2009-01-23 23:50:06 UTC] Michael Fellinger * add shared :mock [84a057d | 2009-01-23 23:49:02 UTC] Michael Fellinger * Fix throw/catch around :respond/:redirect [f56dbe4 | 2009-01-23 23:48:25 UTC] Michael Fellinger * Rename Node#to_view to Node#find_view [0ca8a71 | 2009-01-23 23:47:21 UTC] Michael Fellinger * add CGI to autoload, it's used very seldom [ce88e79 | 2009-01-23 23:46:54 UTC] Michael Fellinger * We need URI for Request [597b9a4 | 2009-01-23 23:46:16 UTC] Michael Fellinger * Add rcov task [a583746 | 2009-01-22 23:01:40 UTC] Michael Fellinger * Don't try to use ERB for things that aren't strings [959e891 | 2009-01-22 23:01:24 UTC] Michael Fellinger * Some improvments for specs, add shared :session [d17596b | 2009-01-22 23:00:50 UTC] Michael Fellinger * redirect_referrer should work like in Ramaze [da7d7c6 | 2009-01-22 23:00:29 UTC] Michael Fellinger * Use r, not Rs [775fa4b | 2009-01-22 23:00:14 UTC] Michael Fellinger * Clean up Helper::Aspect [1286960 | 2009-01-22 22:59:50 UTC] Michael Fellinger * Nicer glob [5551462 | 2009-01-22 22:58:37 UTC] Michael Fellinger * Innate::HelperAccess::helper doesn't extend anymore, do that in your helper as needed [b6675e0 | 2009-01-22 22:57:52 UTC] Michael Fellinger * Remove Innate::Helper::DEFAULT [1a602c3 | 2009-01-22 22:56:26 UTC] Michael Fellinger * Don't fret on existing Innate::ROOT [656c951 | 2009-01-22 22:55:56 UTC] Michael Fellinger * Spec for flash [206a101 | 2009-01-21 18:56:25 UTC] Michael Fellinger * Node automap doesn't need to replace spaces [c518707 | 2009-01-21 18:53:21 UTC] Michael Fellinger * Seems like ERB likes this better [39f033b | 2009-01-21 18:53:10 UTC] Michael Fellinger * Only search public instance methods [696d7af | 2009-01-21 18:52:59 UTC] Michael Fellinger * Compact try_resolve [fd2bb5f | 2009-01-21 18:52:42 UTC] Michael Fellinger * Use Traited in Node, finally gives us inheritable configuration [3891bc2 | 2009-01-21 18:51:51 UTC] Michael Fellinger * Better fulfill_wish [3552421 | 2009-01-21 18:50:58 UTC] Michael Fellinger * remove Action::CONTENT_TYPE, we can add '.sass' in ramaze [5dbfec2 | 2009-01-21 18:49:55 UTC] Michael Fellinger * Nicer output of specs [c6666eb | 2009-01-21 18:49:33 UTC] Michael Fellinger * Specs for Traited [934ba5f | 2009-01-21 18:49:19 UTC] Michael Fellinger * Add Traited, like Ramaze traits, but limited in scope [9b57ea4 | 2009-01-21 12:17:45 UTC] Michael Fellinger * Refactor some Node code, faster arity check and warning on ambiguity for layouts [4853060 | 2009-01-21 12:12:51 UTC] Michael Fellinger * Squeeze slack from Node::automap and Node::setup [4038a4d | 2009-01-21 12:12:10 UTC] Michael Fellinger * Assign layout on include... gotta improve that for inherit [5b8c69b | 2009-01-21 12:10:44 UTC] Michael Fellinger * Don't use RouteExceptions by default, but use CommonLogger [18ab6cb | 2009-01-21 12:10:22 UTC] Michael Fellinger * Remove test code from hello example [c6e0016 | 2009-01-21 12:10:10 UTC] Michael Fellinger * Simpler Innate::View::None [576fc84 | 2009-01-21 12:09:53 UTC] Michael Fellinger * ERB now initialized with '<%>' and sensible filename [42ced1f | 2009-01-21 12:08:59 UTC] Michael Fellinger * Add docs to Innate::DynaMap and accept block on Innate::map [782b029 | 2009-01-21 12:07:51 UTC] Michael Fellinger * Clean up setup of caches, won't register on initialize anymore [cabc6b2 | 2009-01-21 12:07:24 UTC] Michael Fellinger * Add Innate::Cache::DRb [82e0dae | 2009-01-19 18:53:16 UTC] Michael Fellinger * Improve Helper::Redirect and port specs [255643c | 2009-01-18 19:31:31 UTC] Michael Fellinger * Explain how layouts respect provides [87c30c9 | 2009-01-18 19:20:38 UTC] Michael Fellinger * A bit more compact code [27d7f2e | 2009-01-18 19:18:18 UTC] Michael Fellinger * Unify layout/view file lookup so layout respects wish [ba91e65 | 2009-01-18 19:02:46 UTC] Michael Fellinger * Reduce code needed to setup specs [f9d9ef1 | 2009-01-18 19:02:31 UTC] Michael Fellinger * Fixes and improvments for Helper [722336e | 2009-01-18 19:02:08 UTC] Michael Fellinger * Make Innate::middleware less boring [c8ca27e | 2009-01-18 19:01:17 UTC] Michael Fellinger * Pass block to Innate::start to build your middleware [2124ae4 | 2009-01-18 19:00:50 UTC] Michael Fellinger * Innate::Route and Innate::Rewrite behave correct now [96a3674 | 2009-01-18 18:09:02 UTC] Michael Fellinger * Simplify Helper API and add some docs [64420a2 | 2009-01-18 10:26:47 UTC] Michael Fellinger * Don't assign :caller [12f7119 | 2009-01-17 16:20:21 UTC] Michael Fellinger * Add example for error handling [e38b669 | 2009-01-17 16:20:07 UTC] Michael Fellinger * Fix error handling [3bfe38c | 2009-01-17 15:56:08 UTC] Michael Fellinger * Innate::Current isn't needed for static files [e9a9a03 | 2009-01-17 15:55:30 UTC] Michael Fellinger * Heed shadow warnings [eec3639 | 2009-01-17 15:54:56 UTC] Michael Fellinger * More timeout on trap [7a8c8f2 | 2009-01-17 15:54:34 UTC] Michael Fellinger * Add merging for options [9ff7e94 | 2009-01-17 15:34:58 UTC] Michael Fellinger * Exception handling by recall, can you feel the power? [c8e4bec | 2009-01-17 13:12:16 UTC] Michael Fellinger * Check log.color option [97957b9 | 2009-01-17 13:03:25 UTC] Michael Fellinger * Remove Rack::Profile, there's one in rack-contrib [91aab79 | 2009-01-17 13:00:54 UTC] Michael Fellinger * Add Response#reset [2aa69fc | 2009-01-17 13:00:40 UTC] Michael Fellinger * Port Helper::SendFile and spec [8dfca77 | 2009-01-17 12:51:25 UTC] Michael Fellinger * Don't require rubygems twice on specs [db69ee3 | 2009-01-17 12:50:19 UTC] Michael Fellinger * Simple logging options [1c81540 | 2009-01-17 12:49:30 UTC] Michael Fellinger * Minor mod [fba8f58 | 2009-01-17 12:49:01 UTC] Michael Fellinger * Automatic mapping for Node, '/' if only one Node exists [044b979 | 2009-01-17 12:47:23 UTC] Michael Fellinger * Innate::Cache::add method like Ramaze::Cache::add [cda601a | 2009-01-13 18:35:31 UTC] Michael Fellinger * Clean up Node spec [88866be | 2009-01-13 18:32:52 UTC] Michael Fellinger * Fix Session spec [5974e23 | 2009-01-13 18:32:39 UTC] Michael Fellinger * Fix Node spec [675e3bc | 2009-01-13 18:32:05 UTC] Michael Fellinger * Fix aspect spec [1b9a1c8 | 2009-01-13 18:31:43 UTC] Michael Fellinger * Spec Request [0932816 | 2009-01-13 16:35:52 UTC] Michael Fellinger * Port specs for Node parameters [37b1392 | 2009-01-13 16:35:39 UTC] Michael Fellinger * Port specs for Route [972e2de | 2009-01-13 16:35:21 UTC] Michael Fellinger * Reset Response when action is found [58a9143 | 2009-01-13 16:35:04 UTC] Michael Fellinger * Further fixes of provides, only modify the path if a provide is found [b87493f | 2009-01-13 16:32:56 UTC] Michael Fellinger * Fix Innate::Route and add Innate::Rewrite [33be02f | 2009-01-13 16:32:17 UTC] Michael Fellinger * Add Innate::Response [7cedab1 | 2009-01-10 15:59:55 UTC] Michael Fellinger * Add routing middleware [9459903 | 2009-01-09 16:34:40 UTC] Michael Fellinger * Adding aspect helper as default and squeeze out some bugs [170f032 | 2009-01-07 22:01:57 UTC] Michael Fellinger * Some additions and improvments to Request [79979ce | 2009-01-07 21:12:10 UTC] Michael Fellinger * Don't rescue in Node::call so we don't get double backtraces [48f92c1 | 2009-01-07 21:11:17 UTC] Michael Fellinger * render is no helper [13584b8 | 2009-01-07 21:11:07 UTC] Michael Fellinger * LogHub can now be toggled on and off, so you don't have to modify the loggers [88d1c7f | 2009-01-07 21:10:27 UTC] Michael Fellinger * Clean up logging a bit [6036864 | 2009-01-07 20:55:41 UTC] Michael Fellinger * flash is default helper as well [740015b | 2009-01-07 20:52:34 UTC] Michael Fellinger * Add Helper::Flash [753ba5a | 2009-01-07 20:52:14 UTC] Michael Fellinger * Add Innate::Session::Flash [e74d7ac | 2009-01-07 19:09:54 UTC] Michael Fellinger * Spec for Helper::Aspect [f0ba7e7 | 2009-01-07 19:09:40 UTC] Michael Fellinger * Activate default helpers on inclusion of Innate::Node [f1ff921 | 2009-01-07 19:08:39 UTC] Michael Fellinger * Execute Helper::Aspect hooks in Action [6687cd6 | 2009-01-07 19:03:51 UTC] Michael Fellinger * Helper::Partial from Ramaze [470bee9 | 2009-01-06 20:28:18 UTC] TJ Vanderpoel * fixed requires and Wiki#provide to refer to erb instead of haml [015034d | 2009-01-06 20:26:53 UTC] TJ Vanderpoel * converted haml templated to erb [a6fa567 | 2009-01-05 22:15:42 UTC] Michael Fellinger * Don't be so noisy about state [44a11ec | 2009-01-05 22:15:28 UTC] Michael Fellinger * Reduce view glob [2b5dad5 | 2009-01-05 22:15:12 UTC] Michael Fellinger * Action#sync_variables [155d9ad | 2009-01-05 22:14:59 UTC] Michael Fellinger * Don't define ROOT twice [bcce1e2 | 2009-01-05 21:01:04 UTC] Michael Fellinger * The cookie of Mock::Session may be changed [8cb296b | 2009-01-05 20:10:14 UTC] Michael Fellinger * Better lookup so Ramaze can integrate [b4f556d | 2009-01-05 19:06:45 UTC] Michael Fellinger * Action#binding as shortcut [5f5602a | 2009-01-05 18:15:03 UTC] Michael Fellinger * Move all templating engines that have dependencies to Ramaze [91da40d | 2009-01-05 17:58:59 UTC] Michael Fellinger * Remove done todos [4e5f3f2 | 2009-01-05 17:57:48 UTC] Michael Fellinger * Update specs for new options [24ef9cf | 2009-01-05 17:57:31 UTC] Michael Fellinger * Fix options usage in node spec [2ce93fd | 2009-01-05 17:57:14 UTC] Michael Fellinger * Only run Options#dsl instance_eval if block given [1613987 | 2009-01-05 17:46:07 UTC] Michael Fellinger * Expired cache values should not be returned [9849a07 | 2009-01-05 17:41:17 UTC] Michael Fellinger * fix setup for cache spec [25c5303 | 2009-01-05 17:39:19 UTC] Michael Fellinger * Unify requires for specs and don't use Lint [353ebb2 | 2009-01-05 17:38:50 UTC] Michael Fellinger * Allow choice between Fiber and Threads via options [a814522 | 2009-01-05 17:38:20 UTC] Michael Fellinger * Use new options syntax [f8982ae | 2009-01-05 17:32:44 UTC] Michael Fellinger * Refactor sessions, lazy, efficient, and deep [167e44a | 2009-01-05 17:25:52 UTC] Michael Fellinger * Final draft of caching implementation, should fix all problems and be ready for arbitrary backends [8275eb8 | 2009-01-05 17:24:00 UTC] Michael Fellinger * Action#content_type should be public [a565059 | 2009-01-05 15:41:43 UTC] Michael Fellinger * Don't spec spec/innate/cache/common.rb [96caaf5 | 2009-01-05 15:41:18 UTC] Michael Fellinger * Add Options#method_missing and #dsl reopens the previous Options instance [1b564e7 | 2009-01-05 15:40:27 UTC] Michael Fellinger * Require date in rakefile [4fa57b7 | 2009-01-04 17:58:50 UTC] Michael Fellinger * Make trap optional [26d161c | 2009-01-04 15:56:22 UTC] Michael Fellinger * Some more functionality for Options, use it [3a535ea | 2009-01-03 17:24:52 UTC] Michael Fellinger * Better namespaced configuration, not as convenient or magical but much more effective [8522a01 | 2009-01-01 23:00:19 UTC] Michael Fellinger * Allow deleting session data [9ef3b8a | 2009-01-01 23:00:04 UTC] Michael Fellinger * Remove useless stuff from marshal store [75916be | 2009-01-01 22:59:33 UTC] Michael Fellinger * Allow setting port [01fa845 | 2008-12-31 18:51:18 UTC] Michael Fellinger * the session cache defaults already, add more docs for Cache [1d3f663 | 2008-12-31 18:20:34 UTC] Michael Fellinger * Unify Cache::(Marshal|YAML) and simplify specs [a496e6e | 2008-12-31 18:10:06 UTC] Michael Fellinger * Clean up Cache::YAML [08c9bd0 | 2008-12-31 18:09:50 UTC] Michael Fellinger * Add Cache::Marshal [95ec4fc | 2008-12-31 17:32:13 UTC] Michael Fellinger * HTML templates may have .htm extension [d2470a7 | 2008-12-31 17:32:01 UTC] Michael Fellinger * Add Maruku templating engine [10bf350 | 2008-12-31 17:23:13 UTC] Michael Fellinger * Only things that include Node are comparable with it [f41b1ea | 2008-12-31 17:22:32 UTC] Michael Fellinger * Prepare Helper so Ramaze can inject its own path and namespace [940e3f6 | 2008-12-31 17:21:54 UTC] Michael Fellinger * Break up if nothing is mapped [af1da32 | 2008-12-31 17:21:12 UTC] Michael Fellinger * Layout may be a special layout file, a method or a normal template [68cf7c1 | 2008-12-31 17:20:07 UTC] Michael Fellinger * Move VERSION into lib/innate/version.rb [e963c21 | 2008-12-31 17:16:44 UTC] Michael Fellinger * Add erb templating [9fe7fea | 2008-12-31 11:00:33 UTC] Michael Fellinger * Update gemspec [2f70869 | 2008-12-31 11:00:00 UTC] Michael Fellinger * Remove bin/innate from gespec [10acbc0 | 2008-12-31 10:36:57 UTC] Michael Fellinger * Version 2008.12.31 [6e3a0d5 | 2008-12-31 08:21:19 UTC] Pistos * Numerous minor English corrections and adjustments. Signed-off-by: Michael Fellinger [b5ea6a4 | 2008-12-30 21:20:10 UTC] Pistos * A few minor English adjustments in README. Signed-off-by: Michael Fellinger [b85da01 | 2008-12-30 11:02:41 UTC] Pistos * Corrected wrong statement about Innate. Signed-off-by: Michael Fellinger [464a25e | 2008-12-30 10:58:32 UTC] Pistos * One small change in choice of words. Signed-off-by: Michael Fellinger [14e356e | 2008-12-30 10:56:36 UTC] Pistos * Some English adjustments in README. Signed-off-by: Michael Fellinger [2848eb6 | 2008-12-30 17:01:57 UTC] Michael Fellinger * Add spec for options, not passing yet [3c12d1c | 2008-12-30 17:00:49 UTC] Michael Fellinger * Better spec setup [4e58286 | 2008-12-30 17:00:30 UTC] Michael Fellinger * Refactor option.rb [5f56567 | 2008-12-30 16:59:20 UTC] Michael Fellinger * Make use of new caching in Session [b4ff9c1 | 2008-12-30 16:58:14 UTC] Michael Fellinger * Small refactor regarding Innate.options and startup [ad3a45f | 2008-12-30 14:52:48 UTC] Michael Fellinger * Execute update_method_arities only once every request, add docs [b4d956e | 2008-12-30 14:44:09 UTC] Michael Fellinger * Correct order of ancestor lookup, make spec [9e55aa6 | 2008-12-30 14:42:17 UTC] Michael Fellinger * Fix node subclassing, for now [0c6526b | 2008-12-30 10:53:33 UTC] Michael Fellinger * Exapnd readme even more :) [9f6e69e | 2008-12-29 16:14:08 UTC] Michael Fellinger * Update readme with future plans for ramaze [9ac04bd | 2008-12-28 19:06:13 UTC] Michael Fellinger * Update readme, more to come [2e7a9d4 | 2008-12-28 17:52:24 UTC] Michael Fellinger * Don't actually modify repo on release, just output needed steps [c89e0ce | 2008-12-28 17:47:44 UTC] Michael Fellinger * Don't override rubys VERSION [c074bc1 | 2008-12-28 17:45:44 UTC] Michael Fellinger * Really add robust_params now [36157e3 | 2008-12-28 17:42:58 UTC] Michael Fellinger * Update Rakefile with release task [bfc3b84 | 2008-12-28 17:42:35 UTC] Michael Fellinger * Add Request#robust_params and remove useless spec [fb076fa | 2008-12-28 17:30:28 UTC] Michael Fellinger * Add Rakefile [7eebd57 | 2008-12-28 17:30:17 UTC] Michael Fellinger * Add copyright [770e0e7 | 2008-12-28 16:02:22 UTC] Michael Fellinger * Rename whywiki to whywiki_haml [26a4093 | 2008-12-28 15:29:47 UTC] Michael Fellinger * Finally add a gemspec [71f4adc | 2008-12-28 15:29:31 UTC] Michael Fellinger * Remove the favicon.svg [e5a89c4 | 2008-12-28 15:25:28 UTC] Michael Fellinger * Minor update to readme [93dee0b | 2008-12-27 12:47:44 UTC] Michael Fellinger * the nagoro layout uses nagoro of course [2633b69 | 2008-12-27 12:45:59 UTC] Michael Fellinger * Add Nagoro templating engine [93c347f | 2008-12-27 12:45:40 UTC] Michael Fellinger * Add Innate::sync as shortcut for Innate::STATE.sync [d8299a0 | 2008-12-27 12:45:18 UTC] Michael Fellinger * Use __send__ to talk with Node [aad2313 | 2008-12-27 12:44:57 UTC] Michael Fellinger * methods in Innate module are all module_function [1abdaa0 | 2008-12-27 12:44:27 UTC] Michael Fellinger * Use STATE.sync to avoid nested transactions to PStore [c00ad1d | 2008-12-27 12:43:01 UTC] Michael Fellinger * Add whywiki with nagoro templates [ec64847 | 2008-12-27 11:29:52 UTC] Michael Fellinger * Handle empty haml templates gracefully, allow symbols to indicate layout names [c1f528b | 2008-12-27 11:29:15 UTC] Michael Fellinger * Error handling explained [a9f657c | 2008-12-27 11:28:49 UTC] Michael Fellinger * Don't output debugging info on startup anymore [1b6ea66 | 2008-12-27 11:28:18 UTC] Michael Fellinger * Add generic spec helper [ffe012d | 2008-12-27 11:28:01 UTC] Michael Fellinger * Add example/app/whywiki, 15 lines smaller than ramaze (63 LoC) [5d00cf3 | 2008-12-26 22:50:20 UTC] Michael Fellinger * Fix bug in Helper::Link, make specs work [6067687 | 2008-12-26 22:46:55 UTC] Michael Fellinger * A bit of docs for Innate::View [63d2bbd | 2008-12-26 22:46:33 UTC] Michael Fellinger * Document Innate::State::Thread and Innate::State::Fiber [4d8fe6d | 2008-12-26 22:46:09 UTC] Michael Fellinger * Document Innate::StateAccessor [122472e | 2008-12-26 22:45:40 UTC] Michael Fellinger * Minor docs for session [a44618a | 2008-12-26 22:45:11 UTC] Michael Fellinger * Document Innate::Request [853cbb7 | 2008-12-26 22:44:39 UTC] Michael Fellinger * Document Innate::Node [bf4240f | 2008-12-26 22:44:08 UTC] Michael Fellinger * Better Node#action_not_found [ef2d77c | 2008-12-26 22:43:35 UTC] Michael Fellinger * Handle empty PATH_INFO reasonably, log failure [882b793 | 2008-12-26 22:41:40 UTC] Michael Fellinger * Document Innate::Helper [a7c3887 | 2008-12-26 22:41:19 UTC] Michael Fellinger * Document Innate::DynaMap [816dad6 | 2008-12-26 22:41:06 UTC] Michael Fellinger * Document Innate::Current [24bc498 | 2008-12-26 22:40:52 UTC] Michael Fellinger * Document Innate::Adapter [9493582 | 2008-12-26 22:40:07 UTC] Michael Fellinger * Avoid useless variable in the thread wrapper [d989063 | 2008-12-26 22:39:27 UTC] Michael Fellinger * Some improvments to StateAccessor [cf47b2e | 2008-12-26 22:37:39 UTC] Michael Fellinger * Only include Innate::Helper, that will take care of Trinity already [76cd130 | 2008-12-26 22:36:40 UTC] Michael Fellinger * A bit of cleanup for Action [e6b16fc | 2008-12-26 22:36:24 UTC] Michael Fellinger * Add Action#content_type= [f49d415 | 2008-12-26 22:35:54 UTC] Michael Fellinger * Innate::call can optionally take a parameter that indicates the cached middleware stack to use [8b6caa1 | 2008-12-26 22:35:16 UTC] Michael Fellinger * Add Request#local_net? and rename Request#locales to Request#accept_language [02c4df7 | 2008-12-26 22:32:58 UTC] Michael Fellinger * Don't mess up the if innate is there already [bf5c96c | 2008-12-26 22:32:28 UTC] Michael Fellinger * Update README with two quick samples of usage [035b03e | 2008-12-26 22:31:57 UTC] Michael Fellinger * Add new example to show how to spec [bfbcb08 | 2008-12-24 12:27:25 UTC] Michael Fellinger * Give respond/respond! some default values [d491aaa | 2008-12-18 14:23:19 UTC] Michael Fellinger * give middleware_compiler a handy shortcut for static directories [5090bee | 2008-11-16 19:42:43 UTC] Michael Fellinger * Some basic methods for Request [aeebe55 | 2008-11-16 19:42:26 UTC] Michael Fellinger * Minor refactor after a peek via reek [03580f4 | 2008-11-16 19:41:48 UTC] Michael Fellinger * Remove wiki example [ce29024 | 2008-10-10 21:41:46 UTC] Michael Fellinger * Only load coderay stylesheet if set [eafd404 | 2008-10-10 21:39:54 UTC] Michael Fellinger * Speed up index page x3 [a543b33 | 2008-10-10 21:07:27 UTC] Michael Fellinger * Avoid too much debugging output [7e1cf38 | 2008-10-10 21:06:24 UTC] Michael Fellinger * Support feeds in wiki [78338d3 | 2008-10-09 21:08:41 UTC] Michael Fellinger * Major updates to wiki [547e6f9 | 2008-10-09 14:25:54 UTC] Michael Fellinger * History and localization for wiki [866c9a9 | 2008-10-09 12:40:31 UTC] Michael Fellinger * Fix code highlighting [d10d3a5 | 2008-10-06 20:49:47 UTC] Michael Fellinger * Adapt wiki for new loadpath and swfs [73b95f2 | 2008-10-06 20:48:27 UTC] Michael Fellinger * Adding org [cb4289d | 2008-10-06 20:46:37 UTC] Michael Fellinger * Adding the screencasts [864170c | 2008-10-06 20:33:53 UTC] Michael Fellinger * Minor changes to smongrel and emongrel [c96c73b | 2008-10-06 20:33:23 UTC] Michael Fellinger * Fixing the link helper [16b6383 | 2008-10-06 20:32:45 UTC] Michael Fellinger * Adding innate/request [bc3b59d | 2008-10-06 20:32:18 UTC] Michael Fellinger * Current::action and Current::actions [1a302c2 | 2008-10-06 20:30:45 UTC] Michael Fellinger * Major update to wiki, almost done. [e2b07a1 | 2008-10-04 18:56:13 UTC] Michael Fellinger * Layout shouldn't invoke node method again [cf743d0 | 2008-09-30 20:17:31 UTC] Michael Fellinger * Fix typo [4b36ea6 | 2008-09-30 20:15:30 UTC] Michael Fellinger * Wishful thinking, now real! [0d5138e | 2008-09-30 20:15:16 UTC] Michael Fellinger * Refactor of Redirect helper [9a4fa66 | 2008-09-30 20:14:29 UTC] Michael Fellinger * Fix Action, method value has lower priority [a8445bb | 2008-09-30 15:13:53 UTC] Michael Fellinger * Example for the new mime-type based functionality [b8335aa | 2008-09-30 15:13:30 UTC] Michael Fellinger * Intelligently handle requests to *.json or *.yaml [f2ea5cd | 2008-09-30 14:11:57 UTC] Michael Fellinger * Remove debugging output [384306d | 2008-09-30 14:11:25 UTC] Michael Fellinger * View is a module [b1b14df | 2008-09-30 14:11:09 UTC] Michael Fellinger * Incoporate wish into view lookup and simplify [47f4112 | 2008-09-30 14:10:37 UTC] Michael Fellinger * custom middleware setup for wiki [eb2d73b | 2008-09-30 14:10:20 UTC] Michael Fellinger * Wikis git instance should use Log [404c879 | 2008-09-30 00:24:37 UTC] Michael Fellinger * Improve view.rb and add tenjin [d647e68 | 2008-09-30 00:23:32 UTC] Michael Fellinger * Better logging [6ddb623 | 2008-09-30 00:02:43 UTC] Michael Fellinger * Update readme [8e2eefd | 2008-09-28 17:28:20 UTC] Michael Fellinger * View is a module [f6fa84d | 2008-09-28 17:27:51 UTC] Michael Fellinger * Don't fail if no view dir is there, less barking [97da233 | 2008-09-28 17:27:25 UTC] Michael Fellinger * Don't overwrite response.status [0909c3c | 2008-09-28 17:27:12 UTC] Michael Fellinger * Remove cruft from innate.rb [91e0c5a | 2008-09-28 17:26:49 UTC] Michael Fellinger * Allow custom middleware and improve setup [ddb4790 | 2008-09-28 17:24:53 UTC] Michael Fellinger * Move DynaMap into its own file [68be38f | 2008-09-28 17:24:24 UTC] Michael Fellinger * Add custom_middleware example [9b36583 | 2008-09-28 16:35:44 UTC] Michael Fellinger * Add coderay css [76fcd85 | 2008-09-28 16:34:50 UTC] Michael Fellinger * Adding innate/setup.rb as stub for the ramaze one [bbde91a | 2008-09-28 16:34:29 UTC] Michael Fellinger * Extend Innate::View, add Builder [7d5446b | 2008-09-28 16:33:49 UTC] Michael Fellinger * Add mutex for Thread [0031baa | 2008-09-28 16:33:20 UTC] Michael Fellinger * Improve action lookup for templates by ext [b0b4558 | 2008-09-28 16:32:36 UTC] Michael Fellinger * Add Innate.start :file => __FILE__ or :dir => dir [4ed4d95 | 2008-09-28 16:32:03 UTC] Michael Fellinger * autoload for Rack::Profile [ff8a776 | 2008-09-28 16:31:47 UTC] Michael Fellinger * Some refactoring in wiki [9593728 | 2008-09-28 16:31:20 UTC] Michael Fellinger * Caching for git requests, major speedup in wiki [4a836e1 | 2008-09-28 16:30:58 UTC] Michael Fellinger * Using coderay for wiki [56d29c6 | 2008-09-27 14:46:38 UTC] Michael Fellinger * State::Thread relays errors [248f854 | 2008-09-27 14:46:23 UTC] Michael Fellinger * Better Helper::Link#r [c4d3f73 | 2008-09-27 14:45:53 UTC] Michael Fellinger * Improve lookup of app root [4541d8b | 2008-09-26 21:17:54 UTC] Michael Fellinger * Innate::Options#to_hash [5cb29d7 | 2008-09-26 21:17:39 UTC] Michael Fellinger * Improve DEFAULT helper lookup [2dc09bd | 2008-09-26 21:17:27 UTC] Michael Fellinger * Require haml on demand [e52a14f | 2008-09-26 21:17:12 UTC] Michael Fellinger * Revamp Adapter system [590295e | 2008-09-26 21:16:34 UTC] Michael Fellinger * Add Innate::Log stub [6bdea11 | 2008-09-26 21:15:34 UTC] Michael Fellinger * Add example/app/retro_games [b846469 | 2008-09-26 20:39:45 UTC] Michael Fellinger * Add README.md [5804ece | 2008-09-26 19:49:32 UTC] Michael Fellinger * Minor refactor of Action [3483e0c | 2008-09-26 19:31:11 UTC] Michael Fellinger * Remove haml dependency [4ac02fc | 2008-09-26 19:28:32 UTC] Michael Fellinger * Don't require the profile middleware anymore [2912d04 | 2008-09-26 19:23:10 UTC] Michael Fellinger * Smarter helper system * Use the new helper method in your node Following would include Helper::Bar, extend Helper::Foo and include and extend Helper::Foobar class Foo include Innate::Node helper :bar, :extend => :foo, :both => :foobar end * shipped default helpers are found and used automatically, to specify a default helper you can add it to Innate::Helper::DEFAULT. * Helper::EXPOSE is now a reference to Helper::LOOKUP, i think the name makes more sense, it does the usual: exposing public helper methods to lookup for actions. [f8de255 | 2008-09-21 21:08:03 UTC] Michael Fellinger * Add example for Helper::Link [e6f86ba | 2008-09-21 21:07:36 UTC] Michael Fellinger * Mods to spec for Helper::Link [348f504 | 2008-09-21 21:07:09 UTC] Michael Fellinger * Mods to Helper::Link [014537e | 2008-09-21 21:06:39 UTC] Michael Fellinger * Remove debugging output [5ca101e | 2008-09-21 21:06:11 UTC] Michael Fellinger * Default helpers [7a06d13 | 2008-09-21 20:24:59 UTC] Michael Fellinger * Add :secure option to Session [1e7dabf | 2008-09-21 19:58:45 UTC] Michael Fellinger * Adding helper for aspect and redirect [8f0a947 | 2008-09-21 19:57:30 UTC] Michael Fellinger * Catch :respond and :redirect [067f96b | 2008-09-21 19:54:48 UTC] Michael Fellinger * Remove strategy.rb [1a0adb9 | 2008-09-21 19:50:34 UTC] Michael Fellinger * Use Fiber on 1.9 and Thread on 1.8 with less hacks [e4fe857 | 2008-09-20 16:13:37 UTC] Michael Fellinger * Adding session example [1b25235 | 2008-09-20 16:13:25 UTC] Michael Fellinger * Simpler hello example [5c43219 | 2008-09-20 16:12:52 UTC] Michael Fellinger * Adding session and fixing bugs [5b8ad21 | 2008-09-18 19:57:39 UTC] Michael Fellinger * Adding Innate::Helper [0a60a5b | 2008-09-16 13:52:33 UTC] Michael Fellinger * Latest 1.9 finally gives Fiber #initialize, yay! [446ea5a | 2008-09-16 11:51:40 UTC] Michael Fellinger * Remove failed files from reloader cache [c365a60 | 2008-09-16 11:51:07 UTC] Michael Fellinger * Cleanup and put MiddlewareCompiler in own file [ce3b0f6 | 2008-09-16 11:49:37 UTC] Michael Fellinger * Some major updates to the wiki [43fc727 | 2008-09-16 10:22:40 UTC] Michael Fellinger * Caching middleware and improve node lookup * Gives us major speed boost [ac83995 | 2008-09-16 08:36:28 UTC] Michael Fellinger * Improve action compilation [ed1f83a | 2008-09-15 18:17:39 UTC] Michael Fellinger * Initial commit innate-2013.02.21/.load_gemset0000755000004100000410000000025412166103251015675 0ustar www-datawww-data#!/bin/bash [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function* [[ -s .gems ]] && rvm gemset import .gems innate-2013.02.21/MANIFEST0000644000004100000410000000657012166103251014546 0ustar www-datawww-data.gems .gitignore .load_gemset .rvmrc .travis.yml AUTHORS CHANGELOG COPYING MANIFEST README.md Rakefile example/app/retro_games.rb example/app/todo/layout/default.xhtml example/app/todo/spec/todo.rb example/app/todo/start.rb example/app/todo/view/index.xhtml example/app/whywiki_erb/layout/wiki.html.erb example/app/whywiki_erb/spec/wiki.rb example/app/whywiki_erb/start.rb example/app/whywiki_erb/view/edit.erb example/app/whywiki_erb/view/index.erb example/custom_middleware.rb example/hello.rb example/howto_spec.rb example/link.rb example/provides.rb example/session.rb innate.gemspec lib/innate.rb lib/innate/action.rb lib/innate/adapter.rb lib/innate/cache.rb lib/innate/cache/api.rb lib/innate/cache/drb.rb lib/innate/cache/file_based.rb lib/innate/cache/marshal.rb lib/innate/cache/memory.rb lib/innate/cache/yaml.rb lib/innate/current.rb lib/innate/default_middleware.rb lib/innate/dynamap.rb lib/innate/helper.rb lib/innate/helper/aspect.rb lib/innate/helper/cgi.rb lib/innate/helper/flash.rb lib/innate/helper/link.rb lib/innate/helper/redirect.rb lib/innate/helper/render.rb lib/innate/log.rb lib/innate/log/color_formatter.rb lib/innate/log/hub.rb lib/innate/lru_hash.rb lib/innate/mock.rb lib/innate/node.rb lib/innate/options.rb lib/innate/options/dsl.rb lib/innate/options/stub.rb lib/innate/request.rb lib/innate/response.rb lib/innate/route.rb lib/innate/session.rb lib/innate/session/flash.rb lib/innate/spec.rb lib/innate/spec/bacon.rb lib/innate/state.rb lib/innate/state/accessor.rb lib/innate/traited.rb lib/innate/trinity.rb lib/innate/version.rb lib/innate/view.rb lib/innate/view/erb.rb lib/innate/view/etanni.rb lib/innate/view/none.rb spec/example/app/retro_games.rb spec/example/hello.rb spec/example/link.rb spec/example/provides.rb spec/example/session.rb spec/helper.rb spec/innate/action/layout.rb spec/innate/action/layout/file_layout.xhtml spec/innate/cache/common.rb spec/innate/cache/marshal.rb spec/innate/cache/memory.rb spec/innate/cache/yaml.rb spec/innate/dynamap.rb spec/innate/etanni.rb spec/innate/helper.rb spec/innate/helper/aspect.rb spec/innate/helper/cgi.rb spec/innate/helper/flash.rb spec/innate/helper/link.rb spec/innate/helper/redirect.rb spec/innate/helper/render.rb spec/innate/helper/view/aspect_hello.xhtml spec/innate/helper/view/locals.xhtml spec/innate/helper/view/loop.xhtml spec/innate/helper/view/num.xhtml spec/innate/helper/view/partial.xhtml spec/innate/helper/view/recursive.xhtml spec/innate/mock.rb spec/innate/modes.rb spec/innate/node/mapping.rb spec/innate/node/node.rb spec/innate/node/resolve.rb spec/innate/node/view/another_layout/another_layout.xhtml spec/innate/node/view/bar.xhtml spec/innate/node/view/cat2/cat22.xhtml spec/innate/node/view/cat3/cat33.xhtml spec/innate/node/view/foo.html.xhtml spec/innate/node/view/only_view.xhtml spec/innate/node/view/sub/baz.xhtml spec/innate/node/view/sub/foo/baz.xhtml spec/innate/node/view/with_layout.xhtml spec/innate/node/wrap_action_call.rb spec/innate/options.rb spec/innate/parameter.rb spec/innate/provides.rb spec/innate/provides/list.html.xhtml spec/innate/provides/list.txt.xhtml spec/innate/request.rb spec/innate/response.rb spec/innate/route.rb spec/innate/session.rb spec/innate/traited.rb tasks/authors.rake tasks/bacon.rake tasks/changelog.rake tasks/gem.rake tasks/gem_setup.rake tasks/grancher.rake tasks/manifest.rake tasks/rcov.rake tasks/release.rake tasks/reversion.rake tasks/setup.rake tasks/ycov.rake innate-2013.02.21/COPYING0000644000004100000410000000205112166103251014436 0ustar www-datawww-dataCopyright (c) 2008 Michael Fellinger 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 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. innate-2013.02.21/AUTHORS0000644000004100000410000000156012166103251014457 0ustar www-datawww-dataFollowing persons have contributed to innate. (Sorted by number of submitted patches, then alphabetically) 821 Michael Fellinger 31 Tadahiko Uehara 21 Yorick Peterse 9 Lee Jarvis 8 Pistos 5 injekt 5 Ryan Grove 4 Zoxc 3 Antti Tuomi 3 Lin Jen-Shin 2 Andreas Karlsson 2 Arnaud Meuret 2 injekt 2 TJ Vanderpoel 2 YorickPeterse 1 crab 1 Jérémy Zurcher 1 ravage 1 Sam Carr innate-2013.02.21/innate.gemspec0000644000004100000410000001177512166103251016243 0ustar www-datawww-data# -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "innate" s.version = "2013.02.21" s.required_rubygems_version = Gem::Requirement.new(">= 1.3.1") if s.respond_to? :required_rubygems_version= s.authors = ["Michael 'manveru' Fellinger"] s.date = "2013-02-21" s.description = "Simple, straight-forward base for web-frameworks." s.email = "m.fellinger@gmail.com" s.files = [".gems", ".gitignore", ".load_gemset", ".rvmrc", ".travis.yml", "AUTHORS", "CHANGELOG", "COPYING", "MANIFEST", "README.md", "Rakefile", "example/app/retro_games.rb", "example/app/todo/layout/default.xhtml", "example/app/todo/spec/todo.rb", "example/app/todo/start.rb", "example/app/todo/view/index.xhtml", "example/app/whywiki_erb/layout/wiki.html.erb", "example/app/whywiki_erb/spec/wiki.rb", "example/app/whywiki_erb/start.rb", "example/app/whywiki_erb/view/edit.erb", "example/app/whywiki_erb/view/index.erb", "example/custom_middleware.rb", "example/hello.rb", "example/howto_spec.rb", "example/link.rb", "example/provides.rb", "example/session.rb", "innate.gemspec", "lib/innate.rb", "lib/innate/action.rb", "lib/innate/adapter.rb", "lib/innate/cache.rb", "lib/innate/cache/api.rb", "lib/innate/cache/drb.rb", "lib/innate/cache/file_based.rb", "lib/innate/cache/marshal.rb", "lib/innate/cache/memory.rb", "lib/innate/cache/yaml.rb", "lib/innate/current.rb", "lib/innate/default_middleware.rb", "lib/innate/dynamap.rb", "lib/innate/helper.rb", "lib/innate/helper/aspect.rb", "lib/innate/helper/cgi.rb", "lib/innate/helper/flash.rb", "lib/innate/helper/link.rb", "lib/innate/helper/redirect.rb", "lib/innate/helper/render.rb", "lib/innate/log.rb", "lib/innate/log/color_formatter.rb", "lib/innate/log/hub.rb", "lib/innate/lru_hash.rb", "lib/innate/mock.rb", "lib/innate/node.rb", "lib/innate/options.rb", "lib/innate/options/dsl.rb", "lib/innate/options/stub.rb", "lib/innate/request.rb", "lib/innate/response.rb", "lib/innate/route.rb", "lib/innate/session.rb", "lib/innate/session/flash.rb", "lib/innate/spec.rb", "lib/innate/spec/bacon.rb", "lib/innate/state.rb", "lib/innate/state/accessor.rb", "lib/innate/traited.rb", "lib/innate/trinity.rb", "lib/innate/version.rb", "lib/innate/view.rb", "lib/innate/view/erb.rb", "lib/innate/view/etanni.rb", "lib/innate/view/none.rb", "spec/example/app/retro_games.rb", "spec/example/hello.rb", "spec/example/link.rb", "spec/example/provides.rb", "spec/example/session.rb", "spec/helper.rb", "spec/innate/action/layout.rb", "spec/innate/action/layout/file_layout.xhtml", "spec/innate/cache/common.rb", "spec/innate/cache/marshal.rb", "spec/innate/cache/memory.rb", "spec/innate/cache/yaml.rb", "spec/innate/dynamap.rb", "spec/innate/etanni.rb", "spec/innate/helper.rb", "spec/innate/helper/aspect.rb", "spec/innate/helper/cgi.rb", "spec/innate/helper/flash.rb", "spec/innate/helper/link.rb", "spec/innate/helper/redirect.rb", "spec/innate/helper/render.rb", "spec/innate/helper/view/aspect_hello.xhtml", "spec/innate/helper/view/locals.xhtml", "spec/innate/helper/view/loop.xhtml", "spec/innate/helper/view/num.xhtml", "spec/innate/helper/view/partial.xhtml", "spec/innate/helper/view/recursive.xhtml", "spec/innate/mock.rb", "spec/innate/modes.rb", "spec/innate/node/mapping.rb", "spec/innate/node/node.rb", "spec/innate/node/resolve.rb", "spec/innate/node/view/another_layout/another_layout.xhtml", "spec/innate/node/view/bar.xhtml", "spec/innate/node/view/cat2/cat22.xhtml", "spec/innate/node/view/cat3/cat33.xhtml", "spec/innate/node/view/foo.html.xhtml", "spec/innate/node/view/only_view.xhtml", "spec/innate/node/view/sub/baz.xhtml", "spec/innate/node/view/sub/foo/baz.xhtml", "spec/innate/node/view/with_layout.xhtml", "spec/innate/node/wrap_action_call.rb", "spec/innate/options.rb", "spec/innate/parameter.rb", "spec/innate/provides.rb", "spec/innate/provides/list.html.xhtml", "spec/innate/provides/list.txt.xhtml", "spec/innate/request.rb", "spec/innate/response.rb", "spec/innate/route.rb", "spec/innate/session.rb", "spec/innate/traited.rb", "tasks/authors.rake", "tasks/bacon.rake", "tasks/changelog.rake", "tasks/gem.rake", "tasks/gem_setup.rake", "tasks/grancher.rake", "tasks/manifest.rake", "tasks/rcov.rake", "tasks/release.rake", "tasks/reversion.rake", "tasks/setup.rake", "tasks/ycov.rake"] s.homepage = "http://github.com/manveru/innate" s.require_paths = ["lib"] s.rubyforge_project = "innate" s.rubygems_version = "1.8.25" s.summary = "Powerful web-framework wrapper for Rack." if s.respond_to? :specification_version then s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, ["~> 1.5.2"]) s.add_development_dependency(%q, ["~> 1.2.0"]) s.add_development_dependency(%q, ["~> 0.6.2"]) else s.add_dependency(%q, ["~> 1.5.2"]) s.add_dependency(%q, ["~> 1.2.0"]) s.add_dependency(%q, ["~> 0.6.2"]) end else s.add_dependency(%q, ["~> 1.5.2"]) s.add_dependency(%q, ["~> 1.2.0"]) s.add_dependency(%q, ["~> 0.6.2"]) end end innate-2013.02.21/.gitignore0000644000004100000410000000005112166103251015371 0ustar www-datawww-datapkg .yardoc ydoc *~ *.swp coverage *.gem innate-2013.02.21/lib/0000755000004100000410000000000012166103251014153 5ustar www-datawww-datainnate-2013.02.21/lib/innate.rb0000644000004100000410000001747312166103251015772 0ustar www-datawww-data# What can be done with fewer assumptions is done in vain with more. # -- William of Ockham (ca. 1285-1349) # # Name-space of Innate, just about everything goes in here. # # The only exception is Logger::ColorFormatter. # module Innate ROOT = File.expand_path(File.dirname(__FILE__)) unless $LOAD_PATH.any?{|lp| File.expand_path(lp) == ROOT } $LOAD_PATH.unshift(ROOT) end # stdlib require 'digest/md5' require 'digest/sha1' require 'digest/sha2' require 'find' require 'ipaddr' require 'logger' require 'pathname' require 'pp' require 'set' require 'thread' require 'uri' # 3rd party require 'rack' # innate core require 'innate/version' require 'innate/traited' require 'innate/trinity' require 'innate/options/dsl' require 'innate/options/stub' require 'innate/dynamap' # innate full require 'innate/lru_hash' require 'innate/cache' require 'innate/node' require 'innate/options' require 'innate/log' require 'innate/state' require 'innate/current' require 'innate/mock' require 'innate/adapter' require 'innate/action' require 'innate/helper' require 'innate/view' require 'innate/session' require 'innate/session/flash' require 'innate/route' extend Trinity ## # Hash that will contain the middleware for each defined mode. # # @return [Hash] # MIDDLEWARE = {} # Contains all the module functions for Innate, we keep them in a module so # Ramaze can simply use them as well. module SingletonMethods PROXY_OPTIONS = { :port => 'adapter.port', :host => 'adapter.host', :adapter => 'adapter.handler' } ## # Returns an instance of `Rack::Builder` that can be used to start a Innate # application. # # @return [Rack::Builder] # attr_accessor :app # The method that starts the whole business. # # Call Innate.start after you defined your application. # # Usually, this is a blocking call and will not return until the adapter # has finished, which usually happens when you kill the application or hit # ^C. # # We do return if options.started is true, which indicates that all you # wanted to do is setup the environment and update options. # # @example usage # # # passing options # Innate.start :adapter => :mongrel, :mode => :live # # @return [nil] if options.started is true # # @option param :host [String] ('0.0.0.0') # IP address or hostname that we respond to - 0.0.0.0 for all # @option param :port [Fixnum] (7000) # Port for the server # @option param :started [boolean] (false) # Indicate that calls Innate::start will be ignored # @option param :adapter [Symbol] (:webrick) # Web server to run on # @option param :setup [Array] ([Innate::Cache, Innate::Node]) # Will send ::setup to each element during Innate::start # @option param :header [Hash] ({'Content-Type' => 'text/html'}) # Headers that will be merged into the response before Node::call # @option param :trap [String] ('SIGINT') # Trap this signal to issue shutdown, nil/false to disable trap # @option param :mode [Symbol] (:dev) # Indicates which default middleware to use, (:dev|:live) def start(options = {}) root, file = options.delete(:root), options.delete(:file) innate_options = Innate.options found_root = go_figure_root(caller, :root => root, :file => file) innate_options.roots = [*found_root] if found_root # Convert some top-level option keys to the internal ones that we use. PROXY_OPTIONS.each{|given, proxy| options[proxy] = options[given] } options.delete_if{|key, value| PROXY_OPTIONS[key] || value.nil? } # Merge the user's given options into our existing set, which contains defaults. innate_options.merge!(options) setup_dependencies return if innate_options.started innate_options.started = true signal = innate_options.trap trap(signal){ stop(10) } if signal mode = self.options[:mode].to_sym # While Rack itself will spit out errors for invalid instances of # Rack::Builder these errors are typically not very user friendly. if !Innate.app or !MIDDLEWARE[mode] raise( ArgumentError, "The mode \"#{mode}\" does not have a set of middleware defined. " \ "You can define these middleware using " \ "#{self}.middleware(:#{mode}) { ... }" ) end start! end def start!(mode = options[:mode]) Adapter.start(Innate.app) end def stop(wait = 3) Log.info("Shutdown within #{wait} seconds") Timeout.timeout(wait){ teardown_dependencies } Timeout.timeout(wait){ exit } ensure exit! end def setup_dependencies options[:setup].each{|obj| obj.setup if obj.respond_to?(:setup) } end def teardown_dependencies options[:setup].each{|obj| obj.teardown if obj.respond_to?(:teardown) } end def setup options.mode ||= (ENV['RACK_ENV'] || :dev) end # Treat Innate like a rack application, pass the rack +env+ and optionally # the +mode+ the application runs in. # # @param [Hash] env rack env # @param [Symbol] mode indicates the mode of the application # @default mode options.mode # @return [Array] with [body, header, status] # @author manveru def call(env) Innate.app.call(env) end ## # Updates `Innate.app` based on the current mode. # # @param [#to_sym] mode The mode to use. # def recompile_middleware(mode = options[:mode]) mode = mode.to_sym if MIDDLEWARE[mode] and options[:mode] == mode Innate.app = Rack::Builder.new(&MIDDLEWARE[mode]).to_app end end ## # Returns an instance of `Rack::Cascade` for running Innate applications. # This method should be called using `Rack::Builder#run`: # # Innate.middleware(:dev) do # run Innate.core # end # # @return [Rack::Cascade] # def core roots, publics = options[:roots], options[:publics] joined = roots.map { |root| publics.map { |p| File.join(root, p) } } joined = joined.flatten.map { |p| Rack::File.new(p) } current = Current.new(Route.new(DynaMap), Rewrite.new(DynaMap)) return Rack::Cascade.new(joined << current, [404, 405]) end ## # Sets the middleware for the given mode. # # @example # Innate.middleware(:dev) do # use Rack::Head # use Rack::Reloader # # run Innate.core # end # # @param [#to_sym] mode The mode that the middleware belong to. # @param [Proc] block Block containing the middleware. This block will be # passed to an instance of `Rack::Builder` and can thus contain everything # this class allows you to use. # def middleware(mode, &block) MIDDLEWARE[mode.to_sym] = block recompile_middleware(mode) end # @example Innate can be started by: # # Innate.start :file => __FILE__ # Innate.start :root => File.dirname(__FILE__) # # Either setting will surpress the warning that might show up on startup # and tells you it couldn't find an explicit root. # # In case these options are not passed we will try to figure out a file named # `start.rb` in the process' working directory and assume it's a valid point. def go_figure_root(backtrace, options) if root = options[:root] root elsif file = options[:file] File.dirname(file) elsif File.file?('start.rb') Dir.pwd else root = File.dirname(backtrace[0][/^(.*?):\d+/, 1]) Log.warn "No explicit root folder found, assuming it is #{root}" root end end end extend SingletonMethods require 'innate/default_middleware' end innate-2013.02.21/lib/innate/0000755000004100000410000000000012166103251015431 5ustar www-datawww-datainnate-2013.02.21/lib/innate/session.rb0000644000004100000410000001151012166103251017437 0ustar www-datawww-datamodule Innate # Mostly ported from Ramaze, but behaves lazy, no session will be created if # no session is used. # # We keep session data in memory until #flush is called, at which point it # will be persisted completely into the cache, no question asked. # # You may store anything in here that you may also store in the corresponding # store, usually it's best to keep it to things that are safe to Marshal. # # The Session instance is compatible with the specification of rack.session. # # Since the Time class is used to create the cookie expiration timestamp, you # will have to keep the ttl in a reasonable range. # The maximum value that Time can store on a 32bit system is: # Time.at(2147483647) # => Tue Jan 19 12:14:07 +0900 2038 # # The default expiration time for cookies and the session cache was reduced # to a default of 30 days. # This was done to be compatible with the maximum ttl of MemCache. You may # increase this value if you do not use MemCache to persist your sessions. class Session include Optioned options.dsl do o "Key for the session cookie", :key, 'innate.sid' o "Domain the cookie relates to, unspecified if false", :domain, false o "Path the cookie relates to", :path, '/' o "Use secure cookie", :secure, false o "Time of cookie expiration", :expires, nil o "Time to live for session cookies and cache, nil/false will prevent setting", :ttl, (60 * 60 * 24 * 30) # 30 days o "Length of generated Session ID (only applies when using SecureRandom)", :sid_length, 64 o "cookie cannot be accessed through client side script (http://www.owasp.org/index.php/HttpOnly)", :httponly, false end attr_reader :cookie_set, :request, :response, :flash def initialize(request, response) @request, @response = request, response @cookie_set = false @force_new_cookie = false @cache_sid = nil @flash = Flash.new(self) end # Rack interface def store(key, value) cache_sid[key] = value end alias []= store def fetch(key, value = nil) cache_sid[key] end alias [] fetch def delete(key) cache_sid.delete(key) end def clear cache.delete(sid) @cache_sid = nil end # Additional interface def flush(response = @response) return if !@cache_sid or @cache_sid.empty? flash.rotate! cache.store(sid, cache_sid, :ttl => options.ttl) set_cookie(response) end def sid @sid ||= cookie || generate_sid end def resid! cache_sid cache.delete(sid) @sid = generate_sid @force_new_cookie = true end private def cache_sid @cache_sid ||= cache[sid] || {} end def cookie @request.cookies[options.key] end def cache Innate::Cache.session end def set_cookie(response) return if @cookie_set || (!@force_new_cookie && cookie) @cookie_set = true response.set_cookie(options.key, cookie_value) @force_new_cookie = false end def cookie_value o = options cookie = { :domain => o.domain, :path => o.path, :secure => o.secure, :httponly => o.httponly } cookie[:expires] = (Time.now + o.ttl) if o.ttl cookie.merge!(:value => sid) end def generate_sid begin sid = sid_algorithm end while cache[sid] sid end begin require 'securerandom' # Using SecureRandom, optional length. # SecureRandom is available since Ruby 1.8.7. # For Ruby versions earlier than that, you can require the uuidtools gem, # which has a drop-in replacement for SecureRandom. def sid_algorithm; SecureRandom.hex(options.sid_length); end rescue LoadError require 'openssl' # Using OpenSSL::Random for generation, this is comparable in performance # with stdlib SecureRandom and also allows for optional length, it should # have the same behaviour as the SecureRandom::hex method of the # uuidtools gem. def sid_algorithm OpenSSL::Random.random_bytes(options.sid_length / 2).unpack('H*')[0] end rescue LoadError warn "Falling back to low-entropy Session ID generation" warn "Avoid this by upgrading Ruby, installing OpenSSL, or UUIDTools" # Digest::SHA2::hexdigest produces a string of length 64, although # collisions are not very likely, the entropy is still very low and # length is not optional. # # Replacing it with OS-provided random data would take a lot of code and # won't be as cross-platform as Ruby. def sid_algorithm entropy = [ srand, rand, Time.now.to_f, rand, $$, rand, object_id ] Digest::SHA2.hexdigest(entropy.join) end end end end innate-2013.02.21/lib/innate/version.rb0000644000004100000410000000005312166103251017441 0ustar www-datawww-datamodule Innate VERSION = "2013.02.21" end innate-2013.02.21/lib/innate/state/0000755000004100000410000000000012166103251016551 5ustar www-datawww-datainnate-2013.02.21/lib/innate/state/accessor.rb0000644000004100000410000000677512166103251020717 0ustar www-datawww-datamodule Innate # Simplify accessing Thread.current variables. # # Example: # # class Foo # include Innate::StateAccessor # state_accessor :session # # def calculate # session[:num1] + session[:num2] # end # end # # Foo#calculate can now be called from anywhere in your application and it # will have direct access to the session in the current request/response # cycle in a thread-safe way without the need to explicitly pass the session # along. module StateAccessor # Iterate over the names and yield accordingly. # names are either objects responding to #to_sym or hashes. # # It's only used within this module to make the code readable. # # Used below. def self.each(*names) names.each do |name| if name.respond_to?(:to_hash) name.to_hash.each do |key, meth| yield(key.to_sym, meth.to_sym) end else key = meth = name.to_sym yield(key, meth) end end end # Combined state_writer and state_reader. # +initializer+ is a block that may be given and its result will be the new # value in case the method created by state_reader was never called before # and the value wasn't set before. # # Example: # # state_accessor(:session) # state_accessor(:user){ session[:user] } def state_accessor(*names, &initializer) state_writer(*names) state_reader(*names, &initializer) end # Writer accessor to Thread.current[key]= # # Example: # # class Foo # include Innate::StateAccessor # state_writer(:result) # # def calculate # self.result = 42 # end # end # # class Bar # include Innate::StateAccessor # state_reader(:result) # # def calculcate # result * result # end # end # # Foo.new.calculate # => 42 # Bar.new.calculate # => 1764 def state_writer(*names) StateAccessor.each(*names) do |key, meth| class_eval("def %s=(obj) Thread.current[%p] = obj; end" % [meth, key]) end end # Reader accessor for Thread.current[key] # # Example: # # class Foo # include Innate::StateAccessor # state_reader(:session) # state_reader(:random){ rand(100_000) } # # def calculate # val1 = session[:num1] + session[:num2] + random # val2 = session[:num1] + session[:num2] + random # val1 == val2 # => true # end # end # # NOTE: # If given +initializer+, there will be some performance impact since we # cannot use class_eval and have to use define_method instead, we also # have to check every time whether the initializer was executed already. # # In 1.8.x the overhead of define_method is 3x that of class_eval/def # In 1.9.1 the overhead of define_method is 1.5x that of class_eval/def # # This may only be an issue for readers that are called a lot of times. def state_reader(*names, &initializer) StateAccessor.each(*names) do |key, meth| if initializer define_method(meth) do unless Thread.current.key?(key) Thread.current[key] = instance_eval(&initializer) else Thread.current[key] end end else class_eval("def %s; Thread.current[%p]; end" % [meth, key]) end end end end end innate-2013.02.21/lib/innate/route.rb0000644000004100000410000000607012166103251017117 0ustar www-datawww-datamodule Innate # Innate support simple routing using string, regex and lambda based routers. # Route are stored in a dictionary, which supports hash-like access but # preserves order, so routes are evaluated in the order they are added. # # This middleware should wrap Innate::DynaMap. # # Please note that Rack::File is put before Route and Rewrite, that means # that you cannot apply routes to static files unless you add your own route # middleware before. # # String routers are the simplest way to route in Innate. One path is # translated into another: # # Innate::Route[ '/foo' ] = '/bar' # '/foo' => '/bar' # # Regex routers allow matching against paths using regex. Matches within # your regex using () are substituted in the new path using printf-like # syntax. # # Innate::Route[ %r!^/(\d+)\.te?xt$! ] = "/text/%d" # '/123.txt' => '/text/123' # '/789.text' => '/text/789' # # For more complex routing, lambda routers can be used. Lambda routers are # passed in the current path and request object, and must return either a new # path string, or nil. # # Innate::Route[ 'name of route' ] = lambda{ |path, request| # '/bar' if path == '/foo' and request[:bar] == '1' # } # '/foo' => '/foo' # '/foo?bar=1' => '/bar' # # Lambda routers can also use this alternative syntax: # # Innate::Route('name of route') do |path, request| # '/bar' if path == '/foo' and request[:bar] == '1' # end # # NOTE: Use self::ROUTES notation in singleton methods to force correct # lookup. class Route ROUTES = [] def self.[](key) found = self::ROUTES.assoc(key) found[1] if found end def self.[]=(key, value) self::ROUTES.delete_if{|route_key, route_value| route_key == key } self::ROUTES << [key, value] end def self.clear self::ROUTES.clear end def initialize(app = Innate::DynaMap) @app = app end def call(env) path = env['PATH_INFO'] path << '/' if path.empty? if modified = resolve(path) Log.debug("%s routes %p to %p" % [self.class.name, path, modified]) env['PATH_INFO'] = modified end @app.call(env) end def resolve(path) self.class::ROUTES.each do |key, value| if key.is_a?(Regexp) md = path.match(key) return value % md.to_a[1..-1] if md elsif value.respond_to?(:call) new_path = value.call(path, Current.request) return new_path if new_path elsif value.respond_to?(:to_str) return value.to_str if path == key else Log.error("Invalid route %p => %p" % [key, value]) end end nil end end # Identical with Innate::Route, but is called before any Node::call is made class Rewrite < Route ROUTES = [] end module SingletonMethods def Route(key, value = nil, &block) Route[key] = value || block end def Rewrite(key, value = nil, &block) Rewrite[key] = value || block end end end innate-2013.02.21/lib/innate/view.rb0000644000004100000410000000574512166103251016743 0ustar www-datawww-datamodule Innate # This is a container module for wrappers of templating engines and handles # lazy requiring of needed engines. module View include Optioned ENGINE, TEMP = {}, {} options.dsl do o "Cache compiled templates", :cache, true o "Cache template files after they're read to prevent additional filesystem calls", :read_cache, false end # In order to be able to render actions without running # Innate::setup_dependencies we have to add the cache here already. Cache.add(:view) module_function def compile(string) return yield(string.to_s) unless View.options.cache string = string.to_s checksum = Digest::MD5.hexdigest(string) Cache.view[checksum] ||= yield(string) end def exts_of(engine) name = engine.to_s ENGINE.reject{|ext, klass| klass != name }.keys end # Try to obtain given engine by its registered name. def get(engine) if klass = TEMP[engine] return klass elsif klass = ENGINE[engine] TEMP[engine] = obtain(klass) else TEMP[engine] = obtain(engine, View) end end # We need to put this in a Mutex because simultanous calls for the same # class will cause race conditions and one call may return the wrong class # on the first request (before TEMP is set). # No mutex is used in Fiber environment, see Innate::State and subclasses. def obtain(klass, root = Object) Innate.sync do view_name = /^#{klass.to_s.downcase.dup.delete('_')}$/i if view = View.constants.grep(view_name).first root.const_get(view) else raise(NameError, "View #{klass} not found") end end end # Reads the specified view template from the filesystem. When the read_cache # option is enabled, templates will be cached to prevent unnecessary # filesystem reads in the future. # # @example usage # # View.read('some/file.xhtml') # # @param [#to_str] view # # @api private # @see Action#render def read(view) return Cache.view[view] ||= ::File.read(view) if View.options.read_cache ::File.read(view) end # Register given templating engine wrapper and extensions for later usage. # # +name+ : the class name of the templating engine wrapper # +exts+ : any number of arguments will be turned into strings via #to_s # that indicate which filename-extensions the templates may have. def register(klass, *exts) exts.each do |ext| ext = ext.to_s engine = ENGINE[ext] Log.warn("overwriting %p, was set to %p" % [ext, engine]) if engine ENGINE[ext] = klass end end autoload :None, 'innate/view/none' autoload :ERB, 'innate/view/erb' autoload :Etanni, 'innate/view/etanni' register 'Innate::View::None', :css, :html, :htm register 'Innate::View::ERB', :erb register 'Innate::View::Etanni', :xhtml end end innate-2013.02.21/lib/innate/default_middleware.rb0000644000004100000410000000062612166103251021603 0ustar www-datawww-dataInnate.middleware(:dev) do use Rack::Lint use Rack::Head use Rack::ContentLength use Rack::CommonLogger use Rack::ShowExceptions use Rack::ShowStatus use Rack::ConditionalGet use Rack::Reloader, 2 run Innate.core end Innate.middleware(:live) do use Rack::Head use Rack::ContentLength use Rack::CommonLogger use Rack::ShowStatus use Rack::ConditionalGet run Innate.core end innate-2013.02.21/lib/innate/options.rb0000644000004100000410000000167012166103251017455 0ustar www-datawww-datamodule Innate # this has to be run after a couple of other files have been required options.dsl do o "Innate::start will not start an adapter if true", :started, false o "Will send ::setup to each element during Innate::start", :setup, [Innate, Innate::Cache, Innate::Node] o "Trap this signal to issue shutdown, nil/false to disable trap", :trap, 'SIGINT' o "Indicates which default middleware to use, (:dev|:live)", :mode, :dev o "The directories this application resides in", :roots, [File.dirname($0)] o "The directories containing static files to be served", :publics, ['public'] o "Directories containing the view templates", :views, ['view'] o "Directories containing the layout templates", :layouts, ['layout'] o "Prefix used to create relative links", :prefix, '/' trigger(:mode){|value| Innate.recompile_middleware(value) } end end innate-2013.02.21/lib/innate/trinity.rb0000644000004100000410000000063112166103251017460 0ustar www-datawww-datarequire 'innate/state/accessor' require 'innate/request' module Innate # The module to be included into the Controller it basically just provides # #request, #response and #session, each accessing Thread.current to # retrieve the demanded object module Trinity extend StateAccessor state_accessor :request, :response, :session, :actions def action actions.last end end end innate-2013.02.21/lib/innate/options/0000755000004100000410000000000012166103251017124 5ustar www-datawww-datainnate-2013.02.21/lib/innate/options/stub.rb0000644000004100000410000000033412166103251020426 0ustar www-datawww-datamodule Innate # this is just a stub so other modules can register their options in here, # the real options are set in lib/innate.rb class << self; attr_reader :options; end @options = Options.new('Innate') end innate-2013.02.21/lib/innate/options/dsl.rb0000644000004100000410000001232112166103251020232 0ustar www-datawww-datamodule Innate # Provides a minimal DSL to describe options with defaults and metadata. # # The example below should demonstrate the major features, note that key # lookup wanders up the hierarchy until there is a match found or the parent # of the Options class is itself, in which case nil will be returned. # # Usage: # # class Calculator # @options = Options.new(:foo) # def self.options; @options; end # # options.dsl do # o "Which method to use", :method, :plus # o "Default arguments", :args, [1, 2] # sub(:minus){ o("Default arguments", :args, [4, 3]) } # end # # def self.calculate(method = nil, *args) # method ||= options[:method] # args = args.empty? ? options[method, :args] : args # self.send(method, *args) # end # # def self.plus(n1, n2) # n1 + n2 # end # # def self.minus(n1, n2) # n1 - n2 # end # end # # Calculator.calculate # # => 3 # Calculator.options[:method] = :minus # # => :minus # Calculator.calculate # # => 1 # Calculator.calculate(:plus, 4, 5) # # => 9 # class Options def initialize(name, parent = self) @name, @parent, = name, parent @hash = {} yield(self) if block_given? end # Shortcut for instance_eval def dsl(&block) instance_eval(&block) if block self end # Create a new Options instance with +name+ and pass +block+ on to its #dsl. # Assigns the new instance to the +name+ Symbol on current instance. def sub(name, &block) name = name.to_sym case found = @hash[name] when Options found.dsl(&block) else found = @hash[name] = Options.new(name, self).dsl(&block) end found end # Store an option in the Options instance. # # @param [#to_s] doc describing the purpose of this option # @param [#to_sym] key used to access # @param [Object] value may be anything # @param [Hash] other optional Hash containing meta-data # :doc, :value keys will be ignored def option(doc, key, value, other = {}, &block) trigger = block || other[:trigger] convert = {:doc => doc.to_s, :value => value} convert[:trigger] = trigger if trigger @hash[key.to_sym] = other.merge(convert) end alias o option # To avoid lookup on the parent, we can set a default to the internal Hash. # Parameters as in {Options#o}, but without the +key+. def default(doc, value, other = {}) @hash.default = other.merge(:doc => doc, :value => value) end # Add a block that will be called when a new value is set. def trigger(key, &block) @hash[key.to_sym][:trigger] = block end # Try to retrieve the corresponding Hash for the passed keys, will try to # retrieve the key from a parent if no match is found on the current # instance. If multiple keys are passed it will try to find a matching # child and pass the request on to it. def get(key, *keys) if keys.empty? if value = @hash[key.to_sym] value elsif @parent != self @parent.get(key) else nil end elsif sub_options = get(key) sub_options.get(*keys) end end # @param [Array] keys # @param [Object] value def set_value(keys, value) got = get(*keys) return got[:value] = value if got raise(IndexError, "There is no option available for %p" % [keys]) end # Retrieve only the :value from the value hash if found via +keys+. def [](*keys) if value = get(*keys) value.is_a?(Hash) ? value[:value] : value end end # Assign new :value to the value hash on the current instance. # # TODO: allow arbitrary assignments def []=(key, value) ks = key.to_sym if @hash.has_key? ks ns = @hash[ks] ns[:value] = value ns[:trigger].call(value) if ns[:trigger].respond_to?(:call) elsif existing = get(key) option(existing[:doc].to_s.dup, key, value) else raise(ArgumentError, "No key for %p exists" % [key]) end end def method_missing(meth, *args) case meth.to_s when /^(.*)=$/ self[$1] = args.first else self[meth] end end def merge!(hash) hash.each_pair do |key, value| set_value(key.to_s.split('.'), value) end end def to_hash @hash end def each_option(&block) @hash.each(&block) end def each_pair @hash.each do |key, values| yield(key, self[key]) end end def inspect @hash.inspect end def pretty_print(q) q.pp_hash @hash end end # extend your class with this module Optioned def self.included(into) into.extend(SingletonMethods) snaked = into.name.split('::').last snaked = snaked.gsub(/\B[A-Z][^A-Z]/, '_\&').downcase.gsub(' ', '_') options = Innate.options.sub(snaked) into.instance_variable_set(:@options, options) end module SingletonMethods attr_reader :options end private def options self.class.options end end end innate-2013.02.21/lib/innate/mock.rb0000644000004100000410000000202412166103251016705 0ustar www-datawww-datamodule Innate module Mock HTTP_METHODS = %w[ CONNECT DELETE GET HEAD OPTIONS POST PUT TRACE ] OPTIONS = {:app => Innate} HTTP_METHODS.each do |method| (class << self; self; end). send(:define_method, method.downcase){|*args| mock(method, *args) } end def self.mock(method, *args) mock_request.request(method, *args) end def self.mock_request(app = OPTIONS[:app]) Rack::MockRequest.new(app) end def self.session yield Session.new end class Session attr_accessor :cookie def initialize @cookie = nil end HTTP_METHODS.each do |method| define_method(method.downcase){|*args| extract_cookie(method, *args) } end def extract_cookie(method, path, hash = {}) hash['HTTP_COOKIE'] ||= @cookie if @cookie response = Mock::mock(method, path, hash) cookie = response['Set-Cookie'] @cookie = cookie if cookie response end end end end innate-2013.02.21/lib/innate/request.rb0000644000004100000410000000707112166103251017453 0ustar www-datawww-datamodule Innate # Subclass Rack::Request and add some convenient methods. # # An instance is available via the #request method in your Node. # # NOTE: # Please make sure to read the documentation of Rack::Request together with # this, as there are a lot of features available. # # A list of methods from Rack::Request so you get a gist of it: # # ## Generally # # * body # * cookies # * env # * fullpath # * host # * port # * scheme # * url # # ## ENV shortcuts # # * accept_encoding # * content_charset # * content_length # * content_type # * ip # * media_type # * media_type_params # * path_info # * path_info= # * query_string # * referrer # * script_name # * script_name= # * xhr? # # ## Query request method # # * delete? # * get? # * head? # * post? # * put? # * request_method # # ## parameter handling # # * [] # * []= # * form_data? # * params # * values_at class Request < Rack::Request # Currently handled request from Thread.current[:request] # Call it from anywhere via Innate::Request.current def self.current Current.request end # Let's allow #[] to act like #values_at. # # Usage given a GET request like /hey?foo=duh&bar=doh # # request[:foo, :bar] # => ['duh', 'doh'] # # Both +value+ and the elements of +keys+ will be turned into String by #to_s. def [](value, *keys) return super(value) if keys.empty? [value, *keys].map{|key| super(key) } end # the full request URI provided by Rack::Request # e.g. "http://localhost:7000/controller/action?foo=bar.xhtml" def request_uri env['REQUEST_URI'] || env['PATH_INFO'] end # Answers with a subset of request.params with only the key/value pairs for # which you pass the keys. # Valid keys are objects that respond to :to_s # # @example usage # # request.params # # => {'name' => 'jason', 'age' => '45', 'job' => 'lumberjack'} # request.subset('name') # # => {'name' => 'jason'} # request.subset(:name, :job) # # => {'name' => 'jason', 'job' => 'lumberjack'} def subset(*keys) keys = keys.map{|key| key.to_s } params.reject{|key, value| not keys.include?(key) } end # Try to figure out the domain we are running on, this might work for some # deployments but fail for others, given the combination of servers in # front. # # @example usage # # domain # # => # # domain('/foo') # # => # # # @param [#to_s] path # # @return [URI] # # @api external # @author manveru def domain(path = nil, options = {}) uri = URI(self.url) uri.path = path.to_s if path uri.query = nil unless options[:keep_query] uri end ipv4 = %w[ 127.0.0.1/32 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 ] ipv6 = %w[ fc00::/7 fe80::/10 fec0::/10 ::1 ] LOCAL = (ipv4 + ipv6).map{|range| IPAddr.new(range)} unless defined?(LOCAL) # Request is from a local network? # Checks both IPv4 and IPv6 # Answer is true if the IP address making the request is from local network. # Optional argument address can be used to check any IP address. def local_net?(address = ip) addr = IPAddr.new(address) LOCAL.find{|range| range.include?(addr) } rescue ArgumentError => ex raise ArgumentError, ex unless ex.message == 'invalid address' end end end innate-2013.02.21/lib/innate/cache/0000755000004100000410000000000012166103251016474 5ustar www-datawww-datainnate-2013.02.21/lib/innate/cache/api.rb0000644000004100000410000001032712166103251017575 0ustar www-datawww-datamodule Innate class Cache # This is the API every Cache has to conform to. # # The default behaviour is tailored for the Memory cache, override any # behaviour as you need. # # +key+ may be a String or Symbol # +value+ is a Hash of serializable (as according to Marshal) objects # # Every cache instance has to respond to: # # ::new() # #cache_setup(hostname, username, appname, cachename) # #cache_clear() # #cache_delete(*keys) # #cache_fetch(key, default = nil) # #cache_store(key, value, options = {}) # # We are prefixing cache_ to make the intent clear and implementation # easier, as there may be existing behaviour associated with the # non-prefixed version. # # Also note that we create one instance per cache name-space. module API # Executed after #initialize and before any other method. # # Some parameters identifying the current process will be passed so # caches that act in one global name-space can use them as a prefix. # # @param [String #to_s] hostname the hostname of the machine # @param [String #to_s] username user executing the process # @param [String #to_s] appname identifier for the application # @param [String #to_s] cachename namespace, like 'session' or 'action' # @author manveru def cache_setup(hostname, username, appname, cachename) end # Remove all key/value pairs from the cache. # Should behave as if #delete had been called with all +keys+ as argument. # # @author manveru def cache_clear clear end # Remove the corresponding key/value pair for each key passed. # If removing is not an option it should set the corresponding value to nil. # # If only one key was deleted, answer with the corresponding value. # If multiple keys were deleted, answer with an Array containing the values. # # NOTE: Due to differences in the underlying implementation in the # caches, some may not return the deleted value as it would mean # another lookup before deletion. This is the case for caches on # memcached or any database system. # # @param [Object] key the key for the value to delete # @param [Object] keys any other keys to delete as well # @return [Object Array nil] # @author manveru def cache_delete(key, *keys) if keys.empty? if value = yield(key) value[:value] end else [key, *keys].map{|element| cache_delete(element) } end end # Answer with the value associated with the +key+, +nil+ if not found or # expired. # # @param [Object] key the key for which to fetch the value # @param [Object] default will return this if no value was found # @return [Object] # @see Innate::Cache#fetch Innate::Cache#[] # @author manveru def cache_fetch(key, default = nil) value = default if entry = yield(key) if expires = entry[:expires] if expires > Time.now value = entry[:value] else cache_delete(key) end else value = entry[:value] end end return value end # Set +key+ to +value+. # # +options+ may be one of: # :ttl => time to live in seconds if given in Numeric # infinite or maximum if not given # # Usage: # Cache.value.store(:num, 3, :ttl => 20) # Cache.value.fetch(:num) # => 3 # sleep 21 # Cache.value.fetch(:num) # => nil # # @param [Object] key the value is stored with this key # @param [Object] value the key points to this value # @param [Hash] options for now, only :ttl => Fixnum is used. # @see Innate::Cache#store Innate::Cache#[]= # @author manveru def cache_store(key, value, options = {}) ttl = options[:ttl] value_hash = {:value => value} value_hash[:expires] = Time.now + ttl if ttl yield(key, value_hash) return value end end end end innate-2013.02.21/lib/innate/cache/drb.rb0000644000004100000410000000266412166103251017600 0ustar www-datawww-datarequire 'drb' module Innate class Cache # Cache utilizing a DRb server. # # You will need to run a corresponding DRb server to use this cache. The # example below is using a normal Hash, but it is recommended to use a # thread-safe alternative like SyncHash. # # @example usage of DRb server # require 'drb' # # URI = "druby://127.0.0.1:9069" # CACHE = {} # # $SAFE = 1 # disable eval and friends # # DRb.start_service(URI, CACHE) # DRb.thread.join # # Please note that on some Ruby implementations, access to Hash is not # atomic and you might need to lock around access to avoid race conditions. # # @example for all caches # Innate.options.cache.default = Innate::Cache::DRb # # @example for sessions only # Innate.options.cache.session = Innate::Cache::DRb class DRb include Cache::API OPTIONS = {:address => '127.0.0.1', :port => 9069} def cache_setup(*args) address, port = OPTIONS.values_at(:address, :port) @store = DRbObject.new(nil, "druby://#{address}:#{port}") end def cache_clear @store.clear end def cache_store(*args) super{|key, value| @store[key] = value } end def cache_fetch(*args) super{|key| @store[key] } end def cache_delete(*args) super{|key| @store.delete(key) } end end end end innate-2013.02.21/lib/innate/cache/file_based.rb0000644000004100000410000000227112166103251021100 0ustar www-datawww-datamodule Innate class Cache # Used by caches that serialize their contents to the filesystem. # Right now we do not lock around write access to the file outside of the # process, that means that all FileBased caches are not safe for use if you # need more than one instance of your application. module FileBased attr_reader :filename def cache_setup(*args) @prefix = args.compact.join('-') @dir = File.join(Dir.tmpdir, self.class::DIR) FileUtils.mkdir_p(@dir) @filename = File.join(@dir, @prefix + self.class::EXT) @store = self.class::STORE.new(@filename) end def cache_clear FileUtils.mkdir_p(@dir) FileUtils.rm_f(@filename) @store = self.class::STORE.new(@filename) end def cache_store(*args) super{|key, value| transaction{|store| store[key] = value } } end def cache_fetch(*args) super{|key| transaction{|store| store[key] } } end def cache_delete(*args) super{|key| transaction{|store| store.delete(key) } } end def transaction(&block) Innate.sync{ @store.transaction(&block) } end end end end innate-2013.02.21/lib/innate/cache/yaml.rb0000644000004100000410000000077312166103251017772 0ustar www-datawww-datarequire 'yaml/store' module Innate class Cache # Keeps every cache in a separate file like this: # /tmp/innate-cache-yaml/delta-manveru-session.yaml # # The YAML cache is not safe for use between multiple processes, it is also # very slow compared to other caches, so generally the use of it is # discouraged. class YAML include Cache::API include Cache::FileBased STORE = ::YAML::Store DIR = 'innate-cache-yaml' EXT = '.yaml' end end end innate-2013.02.21/lib/innate/cache/marshal.rb0000644000004100000410000000077712166103251020463 0ustar www-datawww-datarequire 'pstore' module Innate class Cache # Keeps every cache in a separate file like this: # /tmp/innate-cache-marshal/delta-manveru-session.marshal # # The Marshal cache is not safe for use between multiple processes, it is # also slow compared to other caches, so generally the use of it is # discouraged. class Marshal include Cache::API include Cache::FileBased STORE = ::PStore DIR = 'innate-cache-marshal' EXT = '.marshal' end end end innate-2013.02.21/lib/innate/cache/memory.rb0000644000004100000410000000072712166103251020337 0ustar www-datawww-datamodule Innate class Cache # Memory cache is simply a Hash with the Cache::API, it's the reference # implementation for every other cache and the default cache. class Memory < Hash include Cache::API def cache_store(*args) super{|key, value| self[key] = value } end def cache_fetch(*args) super{|key| self[key] } end def cache_delete(*args) super{|key| delete(key) } end end end end innate-2013.02.21/lib/innate/spec/0000755000004100000410000000000012166103251016363 5ustar www-datawww-datainnate-2013.02.21/lib/innate/spec/bacon.rb0000644000004100000410000000056112166103251017774 0ustar www-datawww-datarequire 'bacon' require 'rack/test' require File.expand_path('../../', __FILE__) unless defined?(Innate) Bacon.summary_on_exit ENV['RACK_ENV'] = 'TEST' Innate.middleware(:spec) { run Innate.core } Innate.options.started = true Innate.options.mode = :spec shared :rack_test do Innate.setup_dependencies extend Rack::Test::Methods def app; Innate; end end innate-2013.02.21/lib/innate/state.rb0000644000004100000410000000122312166103251017074 0ustar www-datawww-datarequire 'thread' module Innate SEMAPHORE = Mutex.new module SingletonMethods # Use this method to achieve thread-safety for sensitive operations. # # This should be of most use when manipulating files to prevent other # threads from doing the same, no other code will be scheduled during # execution of this method. # # @param [Proc] block the things you want to execute def sync(&block) SEMAPHORE.synchronize(&block) end def defer outer = ::Thread.current ::Thread.new{ inner = ::Thread.current outer.keys.each{|k| inner[k] = outer[k] } yield } end end end innate-2013.02.21/lib/innate/helper.rb0000644000004100000410000001202512166103251017235 0ustar www-datawww-datamodule Innate # Acts as name-space for helpers module Helper # Public instance methods of helpers in here will be recognized as actions LOOKUP = EXPOSE = Set.new # Usually called from Innate::Node::included # We also include Innate::Trinity here, as it may be needed in models when # you use helper methods there. def self.included(into) into.extend(HelperAccess) into.__send__(:include, Trinity) into.helper(*HelpersHelper.options[:default]) end end # Provides access to #helper method without polluting the name-space any # further. module HelperAccess # Convenience method used by Innate::Node. # # Usage: # # class Hi # extend Innate::HelperAccess # helper :cgi, :link, :aspect # end # # This will require the helpers and call: # # Hi.include(Innate::Helper::CGI) # Hi.include(Innate::Helper::Link) # Hi.include(Innate::Helper::Aspect) def helper(*helpers) HelpersHelper.each_include(self, *helpers) end end # Here come the utility methods used from the HelperAccess#helper method, we # do this to keep method count at a minimum and because HelpersHelper is such # an awesome name that just can't be wasted. # # Usage if you want to only extend with helpers: # # class Hi # Innate::HelpersHelper.each_extend(self, :cgi, :link, :aspect) # end # # Usage if you only want to include helpers: # # class Hi # Innate::HelpersHelper.each_include(self, :cgi, :link, :aspect) # end # # Usage for iteration: # # Innate::HelpersHelper.each(:cgi, :link, :aspect) do |mod| # p mod # end # # Usage for translating helpers to modules: # # p Innate::HelpersHelper.each(:cgi, :link, :aspect) module HelpersHelper include Optioned options.dsl do o "Paths that will be searched for helper files", :paths, [Dir.pwd, File.dirname(__FILE__)] o "Namespaces that will be searched for helper modules", :namespaces, [Helper] o "Filename extensions considered for helper files", :exts, %w[rb so bundle] o "Default helpers, added on inclusion of the Helper module", :default, [:aspect, :cgi, :flash, :link, :render, :redirect] end EXTS = %w[rb so bundle] # all of the following are singleton methods module_function # Yield all the modules we can find for the given names of helpers, try to # require them if not available. # # NOTE: Unlike usual #each, this will actually return an Array of the found # modules instead of the given +*names+ # # # Usage: # # Innate::HelpersHelper.each(:cgi, :link, :aspect) do |mod| # p mod # end def each(*names) names.map do |name| if name.class == Module yield(name) if block_given? name elsif mod = get(name) yield(mod) if block_given? mod elsif try_require(name) redo else raise LoadError, "Helper #{name} not found" end end end # Shortcut to extend +into+ with Helper modules corresponding to +*names+. # +into+ has to respond to #extend. # # Usage: # # class Hi # Innate::HelpersHelper.each_extend(self, :cgi, :link, :aspect) # end def each_extend(into, *names, &block) return if names.empty? into.extend(*each(*names, &block)) end # Shortcut to include Helper modules corresponding to +*names+ on +into+. # +into+ has to respond to #include. # #__send__(:include) is used in case #include raises due to being # private/protected # # in case #include is a private/protected method. # # Usage: # # class Hi # Innate::HelpersHelper.each_include(self, :cgi, :link, :aspect) # end def each_include(into, *names, &block) return if names.compact.empty? into.__send__(:include, *each(*names, &block)) end # Based on a simple set of rules we will first construct the most likely # name for the helper and then grep the constants in the Innate::Helper # module for any matches. # # helper :foo_bar # => FooBar # helper :foo # => Foo def get(name) module_name = /^#{name.to_s.dup.delete('_')}(?:helper)?$/i options.namespaces.each do |namespace| found = namespace.constants.grep(module_name).first return namespace.const_get(found) if found end nil end # Figure out files that might have the helper we ask for and then require # the first we find, if any. def try_require(name) if found = find_helper(name.to_s) require(found) || true else raise(LoadError, "Helper #{name} not found") end end def find_helper(name) options.paths.uniq.find do |path| base = ::File.join(path, 'helper', name) options.exts.find do |ext| full = "#{base}.#{ext}" return full if ::File.file?(full) end end end end end innate-2013.02.21/lib/innate/lru_hash.rb0000644000004100000410000000412112166103251017561 0ustar www-datawww-datamodule Innate # A Hash-alike LRU cache that provides fine-grained control over content # restrictions. # # It allows you to set: # * a maximum number of elements # * the maximum amount of memory used for all elements # * the allowed memory-size per element # * time to live # # Differences to the original implementation include: # * The Cache is now a Struct for speed # # Copyright (C) 2002 Yoshinori K. Okuji # Copyright (c) 2009 Michael Fellinger # # You may redistribute it and/or modify it under the same terms as Ruby. class LRUHash < Struct.new(:max_count, :expiration, :hook, :objs, :list) CacheObject = Struct.new(:content, :size, :atime) # On 1.8 we raise IndexError, on 1.9 we raise KeyError KeyError = Module.const_defined?(:KeyError) ? KeyError : IndexError include Enumerable def initialize(options = {}, &hook) self.max_count = options[:max_count] self.expiration = options[:expiration] self.hook = hook self.objs = {} self.list = [] end def delete(key) return unless objs.key?(key) obj = objs[key] hook.call(key, obj.content) if hook objs.delete key list.delete_if{|list_key| key == list_key } obj.content end def clear objs.each{|key, obj| hook.call(key, obj) } if hook objs.clear list.clear end alias invalidate_all clear def expire return unless expiration now = Time.now.to_i list.each_with_index do |key, index| break unless (objs[key].atime + expiration) <= now delete key end end def [](key) expire return unless objs.key?(key) obj = objs[key] obj.atime = Time.now.to_i list.delete_if{|list_key| key == list_key } list << key obj.content end def []=(key, obj) expire delete key if objs.key?(key) delete list.first if max_count && max_count == list.size objs[key] = CacheObject.new(obj, size, Time.now.to_i) list << key obj end end end innate-2013.02.21/lib/innate/current.rb0000644000004100000410000000171412166103251017443 0ustar www-datawww-datarequire 'innate/request' require 'innate/response' module Innate # We track the current request/response/session (Trinity) in Thread.current # so we can reach them from anywhere in the code without passing around the # objects directly. class Current extend Trinity def initialize(app, *rest) if rest.empty? @app = app else @app = Rack::Cascade.new([app, *rest]) end end # Run setup and call the app def call(env) setup(env) @app.call(env) end # Setup new Request/Response/Session for this request/response cycle. # The parameters are here to allow Ramaze to inject its own classes. def setup(env, request = Request, response = Response, session = Session) current = Thread.current req = current[:request] = request.new(env) res = current[:response] = response.new current[:actions] = [] current[:session] = Session.new(req, res) end end end innate-2013.02.21/lib/innate/action.rb0000644000004100000410000001007712166103251017240 0ustar www-datawww-datamodule Innate ACTION_MEMBERS = [ :node, :instance, :method, :params, :method_value, :view, :view_value, :layout, :wish, :options, :variables, :engine, :path ] class Action < Struct.new(*ACTION_MEMBERS) # Create a new Action instance. # Note that the default cannot be a constant as assigning the value objects # to the struct would modify them and might lead to bugs due to persisting # action contents. # # @param [Hash, #to_hash] hash used to seed new Action instance # @return [Action] action with the given defaults from hash # @api stable # @author manveru def self.create(hash = {}) default = {:options => {}, :variables => {}, :params => []} new(*default.merge(hash.to_hash).values_at(*ACTION_MEMBERS)) end def merge!(hash) hash.each_pair{|key, value| send("#{key}=", value) } self end # Call the Action instance, will insert itself temporarily into # Current.actions during the render operation so even in nested calls one # can still access all other Action instances. # Will initialize the assigned node and call Action#render # # @return [String] The rendition of all nested calls # @see Action#render Node#action_found # @api stable # @author manveru def call Current.actions ? wrap_in_current{ render } : render end # @return [Binding] binding of the instance for this Action # @see Node#binding # @api stable # @author manveru def binding instance.binding end # Copy the instance variable names and values from given # from_action#instance into the Action#variables of the action this method # is called on. # # @param [Action #instance] from_action # @return [Action] from_action # @see Action#wrap_in_layout # @api unstable # @author manveru def sync_variables(from_action) instance = from_action.instance instance.instance_variables.each{|variable| name = variable.to_s[1..-1].to_sym self.variables[name] = instance.instance_variable_get(variable) } from_action end # Copy Action#variables as instance variables into the given object. # Defaults to copying the variables to self. # # @param [Object #instance_variable_set] object # @return [NilClass] there is no indication of failure or success # @see Action#render # @author manveru def copy_variables(object = instance) self.variables.each do |iv, value| object.instance_variable_set("@#{iv}", value) end end def render self.instance = instance = node.new self.variables[:content] ||= nil instance.wrap_action_call(self) do copy_variables self.method_value = method ? instance.__send__(method, *params) : nil self.view_value = view ? View.read(view) : nil body, content_type = wrap_in_layout{ engine.call(self, view_value || method_value || '') } options[:content_type] ||= content_type body end end def wrap_in_layout layout ? dup.render_in_layout(&Proc.new) : yield end def render_in_layout self.view, self.method = layout_view_or_method(*layout) self.options[:is_layout] = true self.params = [] self.layout = self.view_value = nil self.sync_variables(self) body, content_type = yield self.sync_variables(self) self.variables[:content] = body return call, content_type end def layout_view_or_method(name, arg) [:layout, :view].include?(name) ? [arg, nil] : [nil, arg] end def wrap_in_current Current.actions << self yield ensure Current.actions.delete(self) end # Try to figure out a sane name for current action. def name File.basename((method || view).to_s).split('.').first end # Path to this action, including params, with the mapping of the current # controller prepended. def full_path File.join(node.mapping, path) end def valid? node.needs_method? ? (method && view) : (method || view) end end end innate-2013.02.21/lib/innate/helper/0000755000004100000410000000000012166103251016710 5ustar www-datawww-datainnate-2013.02.21/lib/innate/helper/aspect.rb0000644000004100000410000001725412166103251020525 0ustar www-datawww-datamodule Innate module Helper ## # The Aspect helper allows you to execute hooks before or after a number of # actions. # # See {Innate::Helper::Aspect::SingletonMethods} for more details on the # various hooks available. # # @example Querying a database before a number of actions. # class Posts # include Innate::Node # # map '/' # helper :aspect # # before(:index, :other) do # @posts = Post.all # end # # def index # return @posts # end # # def other # return @posts[0] # end # end # # This helper is essential for proper working of {Action#render}. # module Aspect ## # Hash containing the various hooks to call for certain actions. # AOP = Hash.new { |h,k| h[k] = Hash.new { |hh,kk| hh[kk] = {} } } ## # Called whenever this helper is included into a class. # # @param [Class] into The class the module was included into. # def self.included(into) into.extend(SingletonMethods) into.add_action_wrapper(5.0, :aspect_wrap) end # Consider objects that have Aspect included def self.ancestral_aop(from) aop = {} from.ancestors.reverse.each do |anc| aop.merge!(AOP[anc]) if anc < Aspect end aop end ## # Calls the aspect for a given position and name. # # @param [#to_sym] position The position of the hook, e.g. :before_all. # @param [#to_sym] name The name of the method for which to call the hook. # def aspect_call(position, name) return unless aop = Aspect.ancestral_aop(self.class) return unless block = at_position = aop[position] block = at_position[name.to_sym] unless at_position.is_a?(Proc) instance_eval(&block) if block end ## # Wraps the specified action between various hooks. # # @param [Innate::Action] action The action to wrap. # def aspect_wrap(action) return yield unless method = action.name aspect_call(:before_all, method) aspect_call(:before, method) result = yield aspect_call(:after, method) aspect_call(:after_all, method) result end ## # This awesome piece of hackery implements action AOP. # # The so-called aspects are simply methods that may yield the next aspect # in the chain, this is similar to racks concept of middleware, but # instead of initializing with an app we simply pass a block that may be # yielded with the action being processed. # # This gives us things like logging, caching, aspects, authentication, # etc. # # Add the name of your method to the trait[:wrap] to add your own method # to the wrap_action_call chain. # # @example adding your method # class MyNode # Innate.node '/' # # private # # def wrap_logging(action) # Innate::Log.info("Executing #{action.name}") # yield # end # # trait[:wrap] # end # # # methods may register themself in the trait[:wrap] and will be called in # left-to-right order, each being passed the action instance and a block # that they have to yield to continue the chain. # # @param [Action] action instance that is being passed to every registered # method # @param [Proc] block contains the instructions to call the action method # if any # @see Action#render # @author manveru # def wrap_action_call(action, &block) return yield if action.options[:is_layout] wrap = SortedSet.new action.node.ancestral_trait_values(:wrap).each{|sset| wrap.merge(sset) } head, *tail = wrap.map{|k,v| v } tail.reverse! combined = tail.inject(block){|s,v| lambda{ __send__(v, action, &s) } } __send__(head, action, &combined) end ## # Module containing various methods that will be made available as class # methods to the class that included {Innate::Helper::Aspect}. # module SingletonMethods include Traited ## # Hook that is called before all the actions in a node. # # @example # class MainController # include Innate::Node # # map '/' # # helper :aspect # # before_all do # puts 'Executed before all actions' # end # # def index # return 'Hello, Innate!' # end # end # def before_all(&block) AOP[self][:before_all] = block end ## # Hook that is called before a specific list of actions. # # @example # class MainController # include Innate::Node # # map '/' # # helper :aspect # # before(:index, :other) do # puts 'Executed before specific actions only.' # end # # def index # return 'Hello, Innate!' # end # # def other # return 'Other method' # end # end # def before(*names, &block) names.each{|name| AOP[self][:before][name] = block } end ## # Hook that is called after all the actions in a node. # # @example # class MainController # include Innate::Node # # map '/' # # helper :aspect # # after_all do # puts 'Executed after all actions' # end # # def index # return 'Hello, Innate!' # end # end # def after_all(&block) AOP[self][:after_all] = block end ## # Hook that is called after a specific list of actions. # # @example # class MainController # include Innate::Node # # map '/' # # helper :aspect # # after(:index, :other) do # puts 'Executed after specific actions only.' # end # # def index # return 'Hello, Innate!' # end # # def other # return 'Other method' # end # end # def after(*names, &block) names.each{|name| AOP[self][:after][name] = block } end ## # Wraps the block around the list of actions resulting in the block # being called both before and after each action. # # @example # class MainController # include Innate::Node # # map '/' # # helper :aspect # # wrap(:index) do # puts 'Wrapped around the index method' # end # # def index # return 'Hello, Innate!' # end # # def other # return 'Other method' # end # end # def wrap(*names, &block) before(*names, &block) after(*names, &block) end def add_action_wrapper(order, method_name) if wrap = trait[:wrap] wrap.merge(SortedSet[[order, method_name.to_s]]) else trait :wrap => SortedSet[[order, method_name.to_s]] end end end # SingletonMethods end # Aspect end # Helper end # Innate innate-2013.02.21/lib/innate/helper/cgi.rb0000644000004100000410000000242312166103251020000 0ustar www-datawww-dataautoload(:CGI, 'cgi') # in case you want to use html_unescape module Innate # Shortcuts to some CGI methods module Helper module CGI module_function # Shortcut for Rack::Utils.escape # # @param [#to_s] input # @return [String] URI-encoded representation of +input+ def url_encode(input) Rack::Utils.escape(input.to_s) end alias u url_encode # Shortcut for Rack::Utils.unescape # # @param [#to_s] input # @return [String] URI-decoded representation of +input+ def url_decode(input) Rack::Utils.unescape(input.to_s) end # Shortcut for Rack::Utils.escape_html # # @param [#to_s] input # @return [String] def html_escape(input) Rack::Utils.escape_html(input.to_s) end # Shortcut for CGI.unescapeHTML # # @param [#to_s] input # @return [String] def html_unescape(input) ::CGI.unescapeHTML(input.to_s) end # safely escape all HTML and code def html_and_code_escape(input) Rack::Utils.escape_html(input.to_s).gsub(/#([{@$]@?)/, '#\1') end alias h html_and_code_escape # aliases are ignored by module_function... module_function :u, :h end end end innate-2013.02.21/lib/innate/helper/redirect.rb0000644000004100000410000000515012166103251021037 0ustar www-datawww-datamodule Innate module Helper module Redirect def respond(body, status = 200, header = {}) response.write body response.status = status header['Content-Type'] ||= Response.mime_type header.each{|key, value| response[key] = value } throw(:respond, response) end def respond!(body, status = 200, header = {}) header['Content-Type'] ||= Response.mime_type throw(:respond, Response.new(body, status, header)) end # +target+ should be anything responding to #to_s. # To check or modify the URI the redirect will go to you may pass a # block, the result value of the block is ignored: # # redirect("/"){|uri| uri.scheme = 'http' } # redirect("/"){|uri| uri.host = 'secure.com' if uri.scheme =~ /s/ } # # +options+ may contain: # # :scheme => "http" | "https" | "ftp" | ... # :host => "localhost" | "foo.com" | "123.123.123.123" | ... # :port => 7000 | "80" | 80 | ... # # :status => 302 | 300 | 303 | ... # :body => "This is a redirect, hold on while we teleport" | ... # # :raw! => true | false | nil | ... # # Note that all options are optional and you may just pass a +target+. def redirect(target, options = {}) target = target.to_s case target when /^http/, /^\// uri = URI(target) else uri = URI("/#{target}") end uri.scheme ||= options[:scheme] || request.scheme uri.host ||= options[:host] || request.host uri.port ||= options[:port] || request.port uri = URI(uri.to_s) yield(uri) if block_given? raw_redirect(uri, options) end def raw_redirect(target, options = {}, &block) header = response.header.merge('Location' => target.to_s) status = options[:status] || 302 body = options[:body] || redirect_body(target) Log.debug "Redirect to: #{target}" throw(:redirect, Response.new(body, status, header, &block)) end def redirect_body(target) "You are being redirected, please follow this link to: " + "#{h target}!" end def redirect_referrer(fallback = Innate.options.prefix) if (referer = request.env['HTTP_REFERER']) && (url = request.url) referer_uri, request_uri = URI(referer), URI(url) redirect(referer) unless referer_uri == request_uri end redirect(fallback) end alias redirect_referer redirect_referrer end end end innate-2013.02.21/lib/innate/helper/flash.rb0000644000004100000410000000176512166103251020343 0ustar www-datawww-datamodule Innate module Helper # Simple access to session.flash. # # Flash is a mechanism using sessions to provide a rotating holder of # key/value pairs. # # Every request that is made will rotate one step, dropping contents stored # two requests ago. # # The purpose of this class is to provide an easy way of setting/retrieving # from the current flash. # # Flash is a way to keep a temporary pairs of keys and values for the duration # of two requests, the current and following. # # Very vague Example: # # On the first request, for example on registering: # # flash[:error] = "You should reconsider your username, it's taken already" # redirect r(:register) # # This is the request from the redirect: # # do_stuff if flash[:error] # # On the request after this, flash[:error] is gone. module Flash # Just for convenience def flash session.flash end end end end innate-2013.02.21/lib/innate/helper/render.rb0000644000004100000410000001161712166103251020522 0ustar www-datawww-datamodule Innate module Helper module Render # Enables you to simply call: # # @example of added functionality # YourController.render_partial(:foo, :x => 42) def self.included(into) into.extend(self) end # Renders the full action in the way a real request would. # # Please be aware that, if this is the first request from a client, you # will not have access to the session in the action being rendered, as no # actual session has been put into place yet. # # It should work as expected on any subsequent requests. # # As usual, patches welcome. # # @example usage # # render_full('/blog/article/1') # render_full('/blog/article/1', :lang => :de) # # Please note that you have to give the full path in the same way you'd # do in a direct request with curl or a browser. # # @api external # @see Mock.session # @author manveru def render_full(path, query = {}) uri = URI(path.to_s) uri.query = Rack::Utils.build_query(query) saved = request, response, session, actions if cookie = request.env['HTTP_COOKIE'] Mock.session do |mock| mock.cookie = cookie return mock.get(uri.to_s).body end else Mock.get(uri.to_s).body end ensure self.request, self.response, self.session, self.actions = saved end # Renders an action without any layout. # You can further tweak the action to be rendered by passing a block. # # @example usage # # render_partial(:index) # render_partial(:index, :title => :foo) # # Please note that you only have to supply the action name, if your # action requires arguments then you have to pass a name suitable for # that. # # @example usage with action that requires arguments # # # requires two arguments # def foo(a, b) # end # # # pass two suitable arguments # render_partial('foo/1/2') # # @api external # @see render_custom # @author manveru def render_partial(action_name, variables = {}) render_custom(action_name, variables) do |action| action.layout = nil yield(action) if block_given? end end # Renders an action view and does not execute any methods. # The rendered view will not be wrapped in a layout and instead # will use the layout of the current action. # You can further tweak the action to be rendered by passing a block. # # @example usage # # render_view(:index) # render_view(:index, :title => :foo) # # @api external # @see render_custom # @author manveru def render_view(action_name, variables = {}) render_custom(action_name, variables) do |action| action.layout = nil action.method = nil yield(action) if block_given? end end # Use the given file as a template and render it in the same scope as # the current action. # The +filename+ may be an absolute path or relative to the process # working directory. # # @example usage # # path = '/home/manveru/example/app/todo/view/index.xhtml' # render_file(path) # render_file(path, :title => :foo) # # Ramaze will emit a warning if you try to render an Action without a # method or view template, but will still try to render it. # The usual {Action#valid?} doesn't apply here, as sometimes you just # cannot have a method associated with a template. # # @api external # @see render_custom # @author manveru def render_file(filename, variables = {}) action = Action.create(:view => filename) action.sync_variables(self.action) action.node = self.class action.engine = self.action.engine action.instance = action.node.new action.variables.merge!(variables) yield(action) if block_given? valid_action = action.view || action.method Log.warn("Empty action: %p" % [action]) unless valid_action action.render end # @api internal # @author manveru def render_custom(action_name, variables = {}) unless action = resolve(action_name.to_s, :needs_method => false) raise(ArgumentError, "No Action %p on #{self}" % [action_name]) end action.sync_variables(self.action) action.instance = action.node.new action.variables = action.variables.merge(variables) yield(action) if block_given? valid_action = action.view || action.method Log.warn("Empty action: %p" % [action]) unless valid_action action.render end end end end innate-2013.02.21/lib/innate/helper/link.rb0000644000004100000410000000625312166103251020200 0ustar www-datawww-datamodule Innate module Helper module Link def self.included(into) into.extend(self) end # Provide the path to given Node and actions. # Escapes GET parameters. # # Usage, mapping is Pages => '/', Users => '/users': # # Pages.r # => URI('/') # Pages.r(:foo) # => URI('/foo') # Pages.r(:foo, :bar) # => URI('/foo/bar') # Pages.r(:foo, :a => :b) # => URI('/foo?a=b') # Pages.r(:foo, :bar, :a => :b) # => URI('/foo/bar?a=b') # # Users.r # => URI('/users/') # Users.r(:foo) # => URI('/users/foo') # Users.r(:foo, :bar) # => URI('/users/foo/bar') # Users.r(:foo, :a => :b) # => URI('/users/foo?a=b') # Users.r(:foo, :bar, :a => :b) # => URI('/users/foo/bar?a=b') # # @return [URI] to the location def route(name = '/', *args) hash = {} hashes, names = args.partition{|arg| arg.respond_to?(:merge!) } hashes.each{|to_merge| hash.merge!(to_merge) } name = name.to_s.gsub(/__/, '/') location = route_location(self) front = Array[location, name, *names.map{|element| Rack::Utils.escape(element) }].join('/').squeeze('/') return URI(front) if hash.empty? query = Rack::Utils.build_query(hash) URI("#{front}?#{query}") end alias r route def route_location(klass) prefix = Innate.options.prefix location = Innate.to(klass) || Innate.to(klass.class) [prefix, location].join('/') end # Create a route to the currently active Node. # # This method is mostly here in case you include this helper elsewhere # and don't want (or can't) type SomeNode.r all the time. # # The usage is identical with {Innate::Helper::Link#route}. # # @param [#to_s] name # @return [URI] to the location # @see Ramaze::Helper::Link#route # @author manveru def route_self(name = '/', *args) Current.action.node.route(name, *args) end alias rs route_self # Create a link tag # # Usage, given Wiki is mapped to `/wiki`: # # Wiki.a(:home) # => 'home' # Wiki.a('home', :home) # => 'home' # Wiki.a('home', :/) # => 'home' # Wiki.a('foo', :/, :foo => :bar) # => 'foo' # Wiki.a('example', 'http://example.com') # # => 'example' # # @return [String] def anchor(text, *args) case first = (args.first || text) when URI href = first.to_s when /^\w+:\/\// uri = URI(first) uri.query = Rack::Utils.escape_html(uri.query) if uri.query href = uri.to_s else href = args.empty? ? r(text) : r(*args) end text = Rack::Utils.escape_html(text) %(#{text}) end alias a anchor end end end innate-2013.02.21/lib/innate/response.rb0000644000004100000410000000110412166103251017610 0ustar www-datawww-datamodule Innate class Response < Rack::Response include Optioned options.dsl do o "Default headers, will not override headers already set", :headers, {'Content-Type' => 'text/html'} end def self.mime_type options[:headers]['Content-Type'] || 'text/html' end def reset self.status = 200 self.header.delete('Content-Type') body.clear self.length = 0 self end def finish options.headers.each{|key, value| self[key] ||= value } Current.session.flush(self) super end end end innate-2013.02.21/lib/innate/log/0000755000004100000410000000000012166103251016212 5ustar www-datawww-datainnate-2013.02.21/lib/innate/log/hub.rb0000644000004100000410000000377712166103251017333 0ustar www-datawww-datamodule Innate # Innate only provides logging via stdlib Logger to avoid bloat and # dependencies, you may specify multiple loggers in the Log instance of LogHub # to accomendate your needs, by default we log to $stderr to be compatible with # CGI. # # Please read the documentation of logger.rb (or even better, its source) to # get a feeling of how to use it correctly within Innate # # A few shortcuts: # # 1. Create logger for stderr/stdout # logger = Logger.new($stdout) # logger = Logger.new($stderr) # # 2. Create logger for a file # # logger = Logger.new('test.log') # # 3. Create logger for file object # # file = File.open('test.log', 'a+') # logger = Logger.new(file) # # 4. Create logger with rotation on specified file size # # # 10 files history, 5 MB each # logger = Logger.new('test.log', 10, (5 << 20)) # # # 100 files history, 1 MB each # logger = Logger.new('test.log', 100, (1 << 20)) # # 5. Create a logger which ages logfiles daily/weekly/monthly # # logger = Logger.new('test.log', 'daily') # logger = Logger.new('test.log', 'weekly') # logger = Logger.new('test.log', 'monthly') class LogHub include Logger::Severity include Optioned attr_accessor :loggers, :program, :active # +loggers+ should be a list of Logger instances def initialize(*loggers) @loggers = loggers.flatten @program = nil @active = true self.level = DEBUG end # set level for all loggers def level=(lvl) @loggers.each{|l| l.level = lvl } @level = lvl end def start; @active = true; end def stop; @active = false; end def method_missing(meth, *args, &block) eval %~ def #{meth}(*args, &block) return unless @active args.each{|arg| @loggers.each{|logger| logger.#{meth}(arg, &block) }} end ~ send(meth, *args, &block) end def write(*args) self.<<(*args) end end end innate-2013.02.21/lib/innate/log/color_formatter.rb0000644000004100000410000000310312166103251021735 0ustar www-datawww-dataclass Logger # Extended Formatter that supports ANSI colors. # # The basic mapping of ANSI colors is as follows: # # | reset | bold | dark | underline | blink | negative # MOD | 0 | 1 | 2 | 4 | 5 | 7 # # | black | red | green | yellow | blue | magenta | cyan | white # FG | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 # BG | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 # # The output is done by: ``\e[#{mod};#{fg};#{bg}m#{string}\e[0m``. # The suffix is to reset the terminal to the original state again. class ColorFormatter < Formatter LEVEL_COLOR = { 'DEBUG' => "\e[0;34;40m%s\e[0m", # blue on black 'INFO' => "\e[0;37;40m%s\e[0m", # white on black 'WARN' => "\e[0;33;40m%s\e[0m", # yellow on black 'ERROR' => "\e[0;31;40m%s\e[0m", # red on black 'FATAL' => "\e[0;35;40m%s\e[0m", # red on black 'UNKNOWN' => "\e[0;32;40m%s\e[0m", # green on black } FORMAT_TIME = "%Y-%m-%d %H:%M:%S" FORMAT_LINE = "%s [%s $%d] %5s | %s: %s\n" def call(severity, time, program, message) hint = severity[0,1] time = format_time(time) pid = $$ string = colorize(msg2str(message), severity) FORMAT_LINE % [hint, time, pid, severity, program, string] end def format_time(time) time.strftime(FORMAT_TIME) end def colorize(string, severity) LEVEL_COLOR[severity] % string end def self.color?(logdev) logdev.respond_to?(:tty?) and logdev.tty? end end end innate-2013.02.21/lib/innate/adapter.rb0000644000004100000410000000516712166103251017407 0ustar www-datawww-data# Rack doesn't ship with ebb handler, but it doesn't get picked up under some # circumstances, so we do that here. # Jruby Rack doesn't have the Handler::register method, so we have to check. if Rack::Handler.respond_to?(:register) Rack::Handler.register('ebb', 'Rack::Handler::Ebb') end module Innate # Lightweight wrapper around Rack::Handler, will apply our options in a # unified manner and deal with adapters that don't like to do what we want or # where Rack doesn't want to take a stand. # # Rack handlers as of 2009.03.25: # cgi, fastcgi, mongrel, emongrel, smongrel, webrick, lsws, scgi, thin module Adapter include Optioned options.dsl do o "IP address or hostname that we respond to - 0.0.0.0 for all", :host, "0.0.0.0" o "Port for the server", :port, 7000 o "Web server to run on", :handler, :webrick end # Pass given app to the Handler, handler is chosen based on config.adapter # option. # If there is a method named start_name_of_adapter it will be run instead # of the default run method of the handler, this makes it easy to define # custom startup of handlers for your server of choice. def self.start(app, given_options = nil) options.merge!(given_options) if given_options handler = options[:handler].to_s.downcase config = { :Host => options[:host], :Port => options[:port] } Log.debug "Using #{handler}" if respond_to?(method = "start_#{handler}") send(method, app, config) else Rack::Handler.get(handler).run(app, config) end end # Due to buggy autoload on Ruby 1.8 we have to require 'ebb' manually. # This most likely happens because autoload doesn't respect the require of # rubygems and uses the C require directly. def self.start_ebb(app, config) require 'ebb' Rack::Handler.get('ebb').run(app, config) end # We want webrick to use our logger. def self.start_webrick(app, config) handler = Rack::Handler.get('webrick') config = { :BindAddress => config[:Host], :Port => config[:Port], :Logger => Log, } handler.run(app, config) end # Thin shouldn't give excessive output, especially not to $stdout def self.start_thin(app, config) handler = Rack::Handler.get('thin') ::Thin::Logging.silent = true handler.run(app, config) end # A simple Unicorn wrapper. def self.start_unicorn(app, config) require 'unicorn' config = { :listeners => ["#{config[:Host]}:#{config[:Port]}"] } ::Unicorn.run(app, config) end end end innate-2013.02.21/lib/innate/dynamap.rb0000644000004100000410000000406212166103251017411 0ustar www-datawww-datamodule Innate class URLMap < Rack::URLMap def initialize(map = {}) @originals = map super end # super may raise when given invalid locations, so we only replace the # `@originals` if we are sure the new map is valid def remap(map) value = super @originals = map value end def map(location, object) return unless location and object remap(@originals.merge(location.to_s => object)) end def delete(location) @originals.delete(location) remap(@originals) end def at(location) @originals[location] end def to(object) @originals.invert[object] end def to_hash @originals.dup end def call(env) raise "Nothing mapped yet" if @originals.empty? super end end DynaMap = URLMap.new # script_name, path_info = env['SCRIPT_NAME'], env['PATH_INFO'] # answer = app.call(env) # env.merge!('SCRIPT_NAME' => script_name, 'PATH_INFO' => path_info) # answer module SingletonMethods # Maps the given +object+ or +block+ to +location+, +object+ must respond to # #call in order to be of any use. # # @example with passed +object+ # # Innate.map('/', lambda{|env| [200, {}, "Hello, World"] }) # Innate.at('/').call({}) # => [200, {}, "Hello, World"] # # @example with passed +block+ # # Innate.map('/'){|env| [200, {}, ['Hello, World!']] } # Innate.at('/').call({}) def map(location, object = nil, &block) DynaMap.map(location, object || block) end # Answer with object at +location+. # # @example # # class Hello # include Innate::Node # map '/' # end # # Innate.at('/') # => Hello def at(location) DynaMap.at(location) end # Returns one of the paths the given +object+ is mapped to. # # @example # # class Hello # include Innate::Node # map '/' # end # # Innate.to(Hello) # => '/' def to(object) DynaMap.to(object) end end end innate-2013.02.21/lib/innate/cache.rb0000644000004100000410000000674112166103251017031 0ustar www-datawww-datamodule Innate # Cache manager and wrapper. # # Provides a convenient wrapper around caches to keep method name confusion # at a minimum while still having short and meaningful method names for every # cache instance. # # The default caching is specified in lib/innate.rb in the config section. # At the time of writing it defaults to Innate::Cache::Memory but can be # changed easily. # # Configuration has to be done before Innate::setup_dependencies is being # called. # # Configuration: # # Innate::Cache.options do |cache| # cache.names = [:session, :user] # cache.session = Innate::Cache::Marshal # cache.user = Innate::Cache::YAML # end # # Usage for storing: # # # Storing with a time to live (10 seconds) # Innate::Cache.user.store(:manveru, "Michael Fellinger", :ttl => 10) # # # Storing indefinitely # Innate::Cache.user[:Pistos] = "unknown" # # or without :ttl argument # Innate::Cache.user.store(:Pistos, "unknown") # # Usage for retrieving: # # # we stored this one for 10 seconds # Innate::Cache.user.fetch(:manveru, 'not here anymore') # # => "Michael Fellinger" # sleep 11 # Innate::Cache.user.fetch(:manveru, 'not here anymore') # # => "not here anymore" # # Innate::Cache.user[:Pistos] # # => "unknown" # Innate::Cache.user.fetch(:Pistos) # # => "unknown" # # # For more details and to find out how to implement your own cache please # read the documentation of Innate::Cache::API # # NOTE: # * Some caches might expose their contents for everyone else on the same # system, or even on connected systems. The rule as usual is, not to # cache sensitive information. class Cache autoload :API, 'innate/cache/api' autoload :DRb, 'innate/cache/drb' autoload :YAML, 'innate/cache/yaml' autoload :Memory, 'innate/cache/memory' autoload :Marshal, 'innate/cache/marshal' autoload :FileBased, 'innate/cache/file_based' include Optioned options.dsl do o "Assign a cache to each of these names on Innate::Cache::setup", :names, [:session, :view] default "If no option for the cache name exists, fall back to this", Innate::Cache::Memory end attr_reader :name, :instance def initialize(name, klass = nil) @name = name.to_s.dup.freeze klass ||= options[@name.to_sym] @instance = klass.new @instance.cache_setup( ENV['HOSTNAME'], ENV['USER'], 'pristine', @name ) end # Add all caches from the options. # # @see Innate::setup_dependencies # @api stable # @return [Array] names of caches initialized # @author manveru def self.setup options.names.each{|name| add(name) } end # Add accessors for cache # # @param [Cache] cache def self.register(cache) key = cache.name.to_s return if respond_to?(key) && respond_to?("#{key}=") (class << self; self; end).send(:attr_accessor, key) send("#{key}=", cache) end def self.add(*names) names.each{|name| register(new(name)) } end def clear instance.cache_clear end def delete(*keys) instance.cache_delete(*keys) end def fetch(key, default = nil) instance.cache_fetch(key, default) end alias [] fetch def store(key, value, options = {}) instance.cache_store(key, value, options) end alias []= store end end innate-2013.02.21/lib/innate/session/0000755000004100000410000000000012166103251017114 5ustar www-datawww-datainnate-2013.02.21/lib/innate/session/flash.rb0000644000004100000410000000403612166103251020541 0ustar www-datawww-datamodule Innate class Session # The purpose of this class is to act as a unifier of the previous # and current flash. # # Flash means pairs of keys and values that are held only over one # request/response cycle. So you can assign a key/value in the current # session and retrieve it in the current and following request. # # Please see the Innate::Helper::Flash for details on the usage in your # application. class Flash include Enumerable def initialize(session) @session = session end # iterate over the combined session def each(&block) combined.each(&block) end # the current session[:FLASH_PREVIOUS] def previous session[:FLASH_PREVIOUS] || {} end # the current session[:FLASH] def current session[:FLASH] ||= {} end # combined key/value pairs of previous and current # current keys overshadow the old ones. def combined previous.merge(current) end # flash[key] in your Controller def [](key) combined[key] end # flash[key] = value in your Controller def []=(key, value) prev = session[:FLASH] || {} prev[key] = value session[:FLASH] = prev end # Inspects combined def inspect combined.inspect end # Delete a key def delete(key) previous.delete(key) current.delete(key) end # check if combined is empty def empty? combined.empty? end # merge into current def merge!(hash) current.merge!(hash) end # merge on current def merge(hash) current.merge(hash) end # Rotation means current values are assigned as old values for the next # request. def rotate! old = session.delete(:FLASH) session[:FLASH_PREVIOUS] = old if old end private # Associated session object def session @session end end end end innate-2013.02.21/lib/innate/traited.rb0000644000004100000410000000471112166103251017415 0ustar www-datawww-datamodule Innate # Traited helps you doing configuration similar to class variables. # # It's built on a simple Hash, where keys are objects and the values the # configuration. # By using {Traited#ancestral_trait} you will get nicely inherited # configuration, where keys later in the ancestors will take precedence. # # @example usage # # class Foo # include Innate::Traited # trait :hello => 'Hello' # # def initialize # trait :hello => 'World!' # end # # def show # [class_trait[:hello], trait[:hello], ancestral_trait[:hello]] # end # end # # Foo.trait[:hello] # => "Hello" # foo = Foo.new # foo.trait[:hello] # => "World!" # foo.show # => ["Hello", "World!", "World!"] module Traited TRAITS, ANCESTRAL_TRAITS, ANCESTRAL_VALUES = {}, {}, {} def self.included(into) into.extend(self) end def trait(hash = nil) if hash TRAITS[self] ||= {} result = TRAITS[self].merge!(hash) ANCESTRAL_VALUES.clear ANCESTRAL_TRAITS.clear result else TRAITS[self] || {} end end # Builds a trait from all the ancestors, closer ancestors overwrite distant # ancestors # # @example # class Foo # include Innate::Traited # trait :one => :eins, :first => :erstes # end # # class Bar < Foo # trait :two => :zwei # end # # class Foobar < Bar # trait :three => :drei, :first => :overwritten # end # # Foobar.ancestral_trait # => { # :three => :drei, :two => :zwei, :one => :eins, :first => :overwritten # } def ancestral_trait klass = self.kind_of?(Module) ? self : self.class ANCESTRAL_TRAITS[klass] ||= each_ancestral_trait({}){|hash, trait| hash.update(trait) } end def ancestral_trait_values(key) klass = self.kind_of?(Module) ? self : self.class cache = ANCESTRAL_VALUES[klass] ||= {} cache[key] ||= each_ancestral_trait([]){|array, trait| array << trait[key] if trait.key?(key) } end def each_ancestral_trait(obj) ancs = respond_to?(:ancestors) ? ancestors : self.class.ancestors ancs.unshift(self) ancs.reverse_each{|anc| yield(obj, TRAITS[anc]) if TRAITS.key?(anc) } obj end # trait for self.class if we are an instance def class_trait respond_to?(:ancestors) ? trait : self.class.trait end end end innate-2013.02.21/lib/innate/log.rb0000644000004100000410000000066512166103251016546 0ustar www-datawww-datarequire 'innate/log/hub' require 'innate/log/color_formatter' module Innate logdev = $stderr logger = Logger.new(logdev) if Logger::ColorFormatter.color?(logdev) begin require 'win32console' if RUBY_PLATFORM =~ /win32/i logger.formatter = Logger::ColorFormatter.new rescue LoadError logger.debug "For colors on windows, please `gem install win32console`" end end Log = LogHub.new(logger) end innate-2013.02.21/lib/innate/view/0000755000004100000410000000000012166103251016403 5ustar www-datawww-datainnate-2013.02.21/lib/innate/view/erb.rb0000644000004100000410000000043612166103251017503 0ustar www-datawww-datarequire 'erb' module Innate module View module ERB def self.call(action, string) erb = View.compile(string){|str| ::ERB.new(str, nil, '%<>') } erb.filename = (action.view || action.method).to_s erb.result(action.binding) end end end end innate-2013.02.21/lib/innate/view/none.rb0000644000004100000410000000023312166103251017665 0ustar www-datawww-datamodule Innate module View module None def self.call(action, string) return string.to_s, Response.mime_type end end end end innate-2013.02.21/lib/innate/view/etanni.rb0000644000004100000410000000174412166103251020214 0ustar www-datawww-datamodule Innate module View module Etanni def self.call(action, string) etanni = View.compile(string) do |str| filename = action.view || action.method Innate::Etanni.new(str, filename) end etanni.result(action.instance) end end end class Etanni SEPARATOR = "E69t116A65n110N78i105S83e101P80a97R82a97T84o111R82" CHOMP = "<<#{SEPARATOR}.chomp!" START = "\n_out_ << #{CHOMP}\n" STOP = "\n#{SEPARATOR}\n" REPLACEMENT = "#{STOP}\\1#{START}" def initialize(template, filename = '') @template = template @filename = filename compile end def compile(filename = @filename) temp = @template.strip temp.gsub!(/<\?r\s+(.*?)\s+\?>/m, REPLACEMENT) @compiled = eval("Proc.new{ _out_ = [#{CHOMP}]\n#{temp}#{STOP}_out_.join }", nil, @filename) end def result(instance, filename = @filename) instance.instance_eval(&@compiled) end end end innate-2013.02.21/lib/innate/node.rb0000644000004100000410000010344312166103251016710 0ustar www-datawww-datamodule Innate # The nervous system of {Innate}, so you can relax. # # Node may be included into any class to make it a valid responder to # requests. # # The major difference between this and the old Ramaze controller is that # every Node acts as a standalone application with its own dispatcher. # # What's also an important difference is the fact that {Node} is a module, so # we don't have to spend a lot of time designing the perfect subclassing # scheme. # # This makes dispatching more fun, avoids a lot of processing that is done by # Rack anyway and lets you tailor your application down to the last action # exactly the way you want without worrying about side-effects to other # {Node}s. # # Upon inclusion, it will also include {Innate::Trinity} and {Innate::Helper} # to provide you with {Innate::Request}, {Innate::Response}, # {Innate::Session} instances, and all the standard helper methods as well as # the ability to simply add other helpers. # # Please note that method_missing will _not_ be considered when building an # {Action}. There might be future demand for this, but for now you can simply # use `def index(*args); end` to make a catch-all action. module Node include Traited attr_reader :method_arities, :layout_templates, :view_templates NODE_LIST = Set.new # These traits are inherited into ancestors, changing a trait in an # ancestor doesn't affect the higher ones. # # class Foo; include Innate::Node; end # class Bar < Foo; end # # Foo.trait[:wrap] == Bar.trait[:wrap] # => true # Bar.trait(:wrap => [:cache_wrap]) # Foo.trait[:wrap] == Bar.trait[:wrap] # => false trait :views => [] trait :layouts => [] trait :layout => nil trait :alias_view => {} trait :provide => {} trait :fast_mappings => false # Caching related traits. trait :cache_provides => false trait :provides_cache => LRUHash.new(:max_count => 100) trait :cache_method_arities => false trait :method_arity_cache => LRUHash.new(:max_count => 100) # @see wrap_action_call trait :wrap => SortedSet.new trait :provide_set => false trait :needs_method => false trait :skip_node_map => false # @see patterns_for trait :separate_default_action => false trait :default_action_name => 'index' # Upon inclusion we make ourselves comfortable. def self.included(into) into.__send__(:include, Helper) into.extend(Trinity, self) NODE_LIST << into return if into.provide_set? into.provide(:html, :engine => :Etanni) into.trait(:provide_set => false) end # node mapping procedure # # when Node is included into an object, it's added to NODE_LIST # when object::map(location) is sent, it maps the object into DynaMap # when Innate.start is issued, it calls Node::setup # Node::setup iterates NODE_LIST and maps all objects not in DynaMap by # using Node::generate_mapping(object.name) as location # # when object::map(nil) is sent, the object will be skipped in Node::setup def self.setup NODE_LIST.each{|node| node.map(generate_mapping(node.name)) unless node.trait[:skip_node_map] } end def self.generate_mapping(object_name = self.name) return '/' if NODE_LIST.size == 1 parts = object_name.split('::').map{|part| part.gsub(/^[A-Z]+/){|sub| sub.downcase }.gsub(/[A-Z]+[^A-Z]/, '_\&') } '/' << parts.join('/').downcase end # Tries to find the relative url that this {Node} is mapped to. # If it cannot find one it will instead generate one based on the # snake_cased name of itself. # # @example Usage: # # class FooBar # include Innate::Node # end # FooBar.mapping # => '/foo_bar' # # @return [String] the relative path to the node # # @api external # @see Innate::SingletonMethods#to # @author manveru def mapping Innate.to(self) end # Shortcut to map or remap this Node. # # @example Usage for explicit mapping: # # class FooBar # include Innate::Node # map '/foo_bar' # end # # Innate.to(FooBar) # => '/foo_bar' # # @example Usage for automatic mapping: # # class FooBar # include Innate::Node # map mapping # end # # Innate.to(FooBar) # => '/foo_bar' # # @param [#to_s] location # # @api external # @see Innate::SingletonMethods::map # @author manveru def map(location) trait :skip_node_map => true Innate.map(location, self) end # Specify which way contents are provided and processed. # # Use this to set a templating engine, custom Content-Type, or pass a block # to take over the processing of the {Action} and template yourself. # # Provides set via this method will be inherited into subclasses. # # The +format+ is extracted from the PATH_INFO, it simply represents the # last extension name in the path. # # The provide also has influence on the chosen templates for the {Action}. # # @example providing RSS with ERB templating # # provide :rss, :engine => :ERB # # Given a request to `/list.rss` the template lookup first tries to find # `list.rss.erb`, if that fails it falls back to `list.erb`. # If neither of these are available it will try to use the return value of # the method in the {Action} as template. # # A request to `/list.yaml` would match the format 'yaml' # # @example providing a yaml version of actions # # class Articles # include Innate::Node # map '/article' # # provide(:yaml, :type => 'text/yaml'){|action, value| value.to_yaml } # # def list # @articles = Article.list # end # end # # @example providing plain text inspect version # # class Articles # include Innate::Node # map '/article' # # provide(:txt, :type => 'text/plain'){|action, value| value.inspect } # # def list # @articles = Article.list # end # end # # @param [Proc] block # upon calling the action, [action, value] will be passed to it and its # return value becomes the response body. # # @option param :engine [Symbol String] # Name of an engine for View::get # @option param :type [String] # default Content-Type if none was set in Response # # @raise [ArgumentError] if neither a block nor an engine was given # # @api external # @see View::get Node#provides # @author manveru # # @note # If you specify a block when calling this method you'll have to take care # of rendering views and the like yourself. If you merely want to set a # extension and content type you can omit the block. # # @todo # The comment of this method may be too short for the effects it has on # the rest of Innate, if you feel something is missing please let me # know. def provide(format, param = {}, &block) if param.respond_to?(:to_hash) param = param.to_hash handler = block || View.get(param[:engine]) content_type = param[:type] else handler = View.get(param) end raise(ArgumentError, "Need an engine or block") unless handler trait("#{format}_handler" => handler, :provide_set => true) trait("#{format}_content_type" => content_type) if content_type end ## # Returns the list of provide handlers. This list is cached after the first # call to this method. # # @return [Hash] # def provides if ancestral_trait[:cache_provides] return ancestral_trait[:provides_cache][self] ||= provide_handlers else return provide_handlers end end ## # @see Innate::Node#provides # @return [Hash] # def provide_handlers ancestral_trait.reject { |key, value| key !~ /_handler$/ } end # This makes the Node a valid application for Rack. # +env+ is the environment hash passed from the Rack::Handler # # We rely on correct PATH_INFO. # # As defined by the Rack spec, PATH_INFO may be empty if it wants the root # of the application, so we insert '/' to make our dispatcher simple. # # Innate will not rescue any errors for you or do any error handling, this # should be done by an underlying middleware. # # We do however log errors at some vital points in order to provide you # with feedback in your logs. # # A lot of functionality in here relies on the fact that call is executed # within Current#call which populates the variables used by Trinity. # So if you use the Node directly as a middleware make sure that you #use # Innate::Current as a middleware before it. # # @param [Hash] env # # @return [Array] # # @api external # @see Response#reset Node#try_resolve Session#flush # @author manveru def call(env) path = env['PATH_INFO'] path << '/' if path.empty? response.reset try_resolve(path).finish end # Let's try to find some valid action for given +path+. # Otherwise we dispatch to {Innate::Node#action_missing}. # # @param [String] path from env['PATH_INFO'] # # @return [Response] # # @api external # @see Node#resolve Node#action_found Node#action_missing # @author manveru def try_resolve(path) action = resolve(path) action ? action_found(action) : action_missing(path) end # Executed once an {Action} has been found. # # Reset the {Innate::Response} instance, catch :respond and :redirect. # {Action#call} has to return a String. # # @param [Action] action # # @return [Innate::Response] # # @api external # @see Action#call Innate::Response # @author manveru def action_found(action) response = catch(:respond){ catch(:redirect){ action.call }} unless response.respond_to?(:finish) self.response.write(response) response = self.response end response['Content-Type'] ||= action.options[:content_type] response end # The default handler in case no action was found, kind of method_missing. # Must modify the response in order to have any lasting effect. # # Reasoning: # * We are doing this is in order to avoid tons of special error handling # code that would impact runtime and make the overall API more # complicated. # * This cannot be a normal action is that methods defined in # {Innate::Node} will never be considered for actions. # # To use a normal action with template do following: # # @example # # class Hi # include Innate::Node # map '/' # # def self.action_missing(path) # return if path == '/not_found' # # No normal action, runs on bare metal # try_resolve('/not_found') # end # # def not_found # # Normal action # "Sorry, I do not exist" # end # end # # @param [String] path # # @api external # @see Innate::Response Node#try_resolve # @author manveru def action_missing(path) response = Current.response response.status = 404 response['Content-Type'] = 'text/plain' response.write("No action found at: %p" % path) response end # Let's get down to business, first check if we got any wishes regarding # the representation from the client, otherwise we will assume he wants # html. # # @param [String] path # @param [Hash] options # # @return [nil, Action] # # @api external # @see Node::find_provide Node::update_method_arities Node::find_action # @author manveru def resolve(path, options = {}) name, wish, engine = find_provide(path) node = (respond_to?(:ancestors) && respond_to?(:new)) ? self : self.class action = Action.create( :node => node, :wish => wish, :engine => engine, :path => path, :options => options ) if !action.options.key?(:needs_method) action.options[:needs_method] = node.needs_method? end if content_type = node.ancestral_trait["#{wish}_content_type"] action.options[:content_type] = content_type end node.update_method_arities node.update_template_mappings node.fill_action(action, name) end # Resolve possible provides for the given +path+ from # {Innate::Node#provides}. # # @param [String] path # # @return [Array] with name, wish, engine # # @api internal # @see Node::provide Node::provides # @author manveru def find_provide(path) pr = provides name, wish, engine = path, 'html', pr['html_handler'] pr.find do |key, value| key = key[/(.*)_handler$/, 1] next unless path =~ /^(.+)\.#{key}$/i name, wish, engine = $1, key, value end return name, wish, engine end # Now we're talking {Action}, we try to find a matching template and # method, if we can't find either we go to the next pattern, otherwise we # answer with an {Action} with everything we know so far about the demands # of the client. # # @param [String] given_name the name extracted from REQUEST_PATH # @return [Action, nil] # # @api internal # @see Node#find_method Node#find_view Node#find_layout Node#patterns_for # Action#wish Action#merge! # @author manveru def fill_action(action, given_name) needs_method = action.options[:needs_method] wish = action.wish patterns_for(given_name) do |name, params| method = find_method(name, params) next unless method if needs_method next unless method if params.any? next unless (view = find_view(name, wish)) || method params.map!{|param| Rack::Utils.unescape(param) } action.merge!(:method => method, :view => view, :params => params, :layout => find_layout(name, wish)) end end # Try to find a suitable value for the layout. This may be a template or # the name of a method. # # If a layout could be found, an Array with two elements is returned, the # first indicating the kind of layout (:layout|:view|:method), the second # the found value, which may be a String or Symbol. # # @param [String] name # @param [String] wish # # @return [Array, nil] # # @api external # @see Node#to_layout Node#find_method Node#find_view # @author manveru # # @todo allow layouts combined of method and view... hairy :) def find_layout(name, wish) return unless layout = ancestral_trait[:layout] return unless layout = layout.call(name, wish) if layout.respond_to?(:call) if found = to_layout(layout, wish) [:layout, found] elsif found = find_view(layout, wish) [:view, found] elsif found = find_method(layout, []) [:method, found] end end # We check arity if possible, but will happily dispatch to any method that # has default parameters. # If you don't want your method to be responsible for messing up a request # you should think twice about the arguments you specify due to limitations # in Ruby. # # So if you want your method to take only one parameter which may have a # default value following will work fine: # # def index(foo = "bar", *rest) # # But following will respond to /arg1/arg2 and then fail due to ArgumentError: # # def index(foo = "bar") # # Here a glance at how parameters are expressed in arity: # # def index(a) # => 1 # def index(a = :a) # => -1 # def index(a, *r) # => -2 # def index(a = :a, *r) # => -1 # # def index(a, b) # => 2 # def index(a, b, *r) # => -3 # def index(a, b = :b) # => -2 # def index(a, b = :b, *r) # => -2 # # def index(a = :a, b = :b) # => -1 # def index(a = :a, b = :b, *r) # => -1 # # @param [String, Symbol] name # @param [Array] params # # @return [String, Symbol] # # @api external # @see Node#fill_action Node#find_layout # @author manveru # # @todo Once 1.9 is mainstream we can use Method#parameters to do accurate # prediction def find_method(name, params) return unless arity = method_arities[name.to_s] name if arity == params.size || arity < 0 end # Answer with a hash, keys are method names, values are method arities. # # Note that this will be executed once for every request, once we have # settled things down a bit more we can switch to update based on Reloader # hooks and update once on startup. # However, that may cause problems with dynamically created methods, so # let's play it safe for now. # # @example # # Hi.update_method_arities # # => {'index' => 0, 'foo' => -1, 'bar' => 2} # # @api internal # @see Node#resolve # @return [Hash] mapping the name of the methods to their arity def update_method_arities if ancestral_trait[:cache_method_arities] \ and ancestral_trait[:method_arity_cache][self] return ancestral_trait[:method_arity_cache][self] end @method_arities = {} exposed = ancestors & Helper::EXPOSE.to_a higher = ancestors.select{|ancestor| ancestor < Innate::Node } (higher + exposed).reverse_each do |ancestor| ancestor.public_instance_methods(false).each do |im| @method_arities[im.to_s] = ancestor.instance_method(im).arity end end if ancestral_trait[:cache_method_arities] ancestral_trait[:method_arity_cache][self] = @method_arities end @method_arities end # Try to find the best template for the given basename and wish and respect # aliased views. # # @param [#to_s] action_name # @param [#to_s] wish # # @return [String, nil] depending whether a template could be found # # @api external # @see Node#to_template Node#find_aliased_view # @author manveru def find_view(action_name, wish) aliased = find_aliased_view(action_name, wish) return aliased if aliased to_view(action_name, wish) end # Try to find the best template for the given basename and wish. # # This method is mostly here for symetry with {Innate::Node#to_layout} and # to allow you overriding the template lookup easily. # # @param [#to_s] action_name # @param [#to_s] wish # # @return [String, nil] depending whether a template could be found # # @api external # @see {Node#find_view} {Node#to_template} {Node#root_mappings} # {Node#view_mappings} {Node#to_template} # @author manveru def to_view(action_name, wish) return unless files = view_templates[wish.to_s] files[action_name.to_s] end # Aliasing one view from another. # The aliases are inherited, and the optional third +node+ parameter # indicates the Node to take the view from. # # The argument order is identical with `alias` and `alias_method`, which # quite honestly confuses me, but at least we stay consistent. # # @example # class Foo # include Innate::Node # # # Use the 'foo' view when calling 'bar' # alias_view 'bar', 'foo' # # # Use the 'foo' view from FooBar node when calling 'bar' # alias_view 'bar', 'foo', FooBar # end # # Note that the parameters have been simplified in comparision with # Ramaze::Controller::template where the second parameter may be a # Controller or the name of the template. We take that now as an optional # third parameter. # # @param [#to_s] to view that should be replaced # @param [#to_s] from view to use or Node. # @param [#nil?, Node] node optionally obtain view from this Node # # @api external # @see Node::find_aliased_view # @author manveru def alias_view(to, from, node = nil) trait[:alias_view] || trait(:alias_view => {}) trait[:alias_view][to.to_s] = node ? [from.to_s, node] : from.to_s end # Resolve one level of aliasing for the given +action_name+ and +wish+. # # @param [String] action_name # @param [String] wish # # @return [nil, String] the absolute path to the aliased template or nil # # @api internal # @see Node::alias_view Node::find_view # @author manveru def find_aliased_view(action_name, wish) aliased_name, aliased_node = ancestral_trait[:alias_view][action_name] return unless aliased_name aliased_node ||= self aliased_node.update_view_mappings aliased_node.find_view(aliased_name, wish) end # Find the best matching action_name for the layout, if any. # # This is mostly an abstract method that you might find handy if you want # to do vastly different layout lookup. # # @param [String] action_name # @param [String] wish # # @return [nil, String] the absolute path to the template or nil # # @api external # @see {Node#to_template} {Node#root_mappings} {Node#layout_mappings} # @author manveru def to_layout(action_name, wish) return unless files = layout_templates[wish.to_s] files[action_name.to_s] end # Define a layout to use on this Node. # # A Node can only have one layout, although the template being chosen can # depend on {Innate::Node#provides}. # # @example # layout :foo # @example # layout do |name, wish| # name == 'foo' ? 'dark' : 'bright' # end # @example # layout :foo do |name, wish| # wish == 'html' # end # # @param [String, #to_s] layout_name basename without extension of the # layout to use # @param [Proc, #call] block called on every dispatch if no name given # # @return [Proc, String] The assigned name or block # # @api external # @see Node#find_layout Node#layout_paths Node#to_layout Node#app_layout # @author manveru def layout(layout_name = nil, &block) if layout_name and block # default name, but still check with block trait(:layout => lambda{|name, wish| layout_name.to_s if block.call(name, wish) }) elsif layout_name # name of a method or template trait(:layout => layout_name.to_s) elsif block # call block every request with name and wish, returned value is name # of layout template or method trait(:layout => block) else # remove layout for this node trait(:layout => nil) end return ancestral_trait[:layout] end # The innate beauty in Nitro, Ramaze, and {Innate}. # # Will yield the name of the action and parameter for the action method in # order of significance. # # def foo__bar # responds to /foo/bar # def foo(bar) # also responds to /foo/bar # # But foo__bar takes precedence because it's more explicit. # # The last fallback will always be the index action with all of the path # turned into parameters. # # @example yielding possible combinations of action names and params # # class Foo; include Innate::Node; map '/'; end # # Foo.patterns_for('/'){|action, params| p action => params } # # => {"index"=>[]} # # Foo.patterns_for('/foo/bar'){|action, params| p action => params } # # => {"foo__bar"=>[]} # # => {"foo"=>["bar"]} # # => {"index"=>["foo", "bar"]} # # Foo.patterns_for('/foo/bar/baz'){|action, params| p action => params } # # => {"foo__bar__baz"=>[]} # # => {"foo__bar"=>["baz"]} # # => {"foo"=>["bar", "baz"]} # # => {"index"=>["foo", "bar", "baz"]} # # @param [String, #split] path usually the PATH_INFO # # @return [Action] it actually returns the first non-nil/false result of yield # # @api internal # @see Node#fill_action # @author manveru def patterns_for(path) default_action_name = ancestral_trait[:default_action_name] separate_default_action = ancestral_trait[:separate_default_action] atoms = path.split('/') atoms.delete('') result = nil atoms.size.downto(0) do |len| action_name = atoms[0...len].join('__') next if separate_default_action && action_name == default_action_name params = atoms[len..-1] action_name = default_action_name if action_name.empty? && (separate_default_action || params != [default_action_name]) return result if result = yield(action_name, params) end return nil end # Try to find a template at the given +path+ for +wish+. # # Since Innate supports multiple paths to templates the +path+ has to be an # Array that may be nested one level. # # @example Usage to find available templates # # # This assumes following files: # # view/foo.erb # # view/bar.erb # # view/bar.rss.erb # # view/bar.yaml.erb # # class FooBar # Innate.node('/') # end # # FooBar.to_template(['.', 'view', '/', 'foo'], 'html') # # => "./view/foo.erb" # FooBar.to_template(['.', 'view', '/', 'foo'], 'yaml') # # => "./view/foo.erb" # FooBar.to_template(['.', 'view', '/', 'foo'], 'rss') # # => "./view/foo.erb" # # FooBar.to_template(['.', 'view', '/', 'bar'], 'html') # # => "./view/bar.erb" # FooBar.to_template(['.', 'view', '/', 'bar'], 'yaml') # # => "./view/bar.yaml.erb" # FooBar.to_template(['.', 'view', '/', 'bar'], 'rss') # # => "./view/bar.rss.erb" # # @param [Array>, Array] path # array containing strings and nested (1 level) arrays containing strings # @param [String] wish # # @return [nil, String] relative path to the first template found # # @api external # @see Node#find_view Node#to_layout Node#find_aliased_view # @author manveru def to_template(path, wish) to_view(path, wish) || to_layout(path, wish) end def update_template_mappings update_view_mappings update_layout_mappings end def update_view_mappings if ancestral_trait[:fast_mappings] return @view_templates if @view_templates end paths = possible_paths_for(view_mappings) @view_templates = update_mapping_shared(paths) end def update_layout_mappings if ancestral_trait[:fast_mappings] return @layout_templates if @layout_templates end paths = possible_paths_for(layout_mappings) @layout_templates = update_mapping_shared(paths) end def update_mapping_shared(paths) mapping = {} paths.reject!{|path| !File.directory?(path) } provides.each do |wish_key, engine| wish = wish_key[/(.*)_handler/, 1] exts = possible_exts_for(wish) paths.reverse_each do |path| Find.find(path) do |file| exts.each do |ext| next unless file =~ ext case file.sub(path, '').gsub('/', '__') when /^(.*)\.(.*)\.(.*)$/ action_name, wish_ext, engine_ext = $1, $2, $3 when /^(.*)\.(.*)$/ action_name, wish_ext, engine_ext = $1, wish, $2 end mapping[wish_ext] ||= {} mapping[wish_ext][action_name] = file end end end end return mapping end # Answer with an array of possible paths in order of significance for # template lookup of the given +mappings+. # # @param [#map] mappings An array two Arrays of inner and outer directories. # # @return [Array] # @see update_view_mappings update_layout_mappings update_template_mappings # @author manveru def possible_paths_for(mappings) root_mappings.map{|root| mappings.first.map{|inner| mappings.last.map{|outer| ::File.join(root, inner, outer, '/') }}}.flatten end # Answer with an array of possible extensions in order of significance for # the given +wish+. # # @param [#to_s] wish the extension (no leading '.') # # @return [Array] list of exts valid for this +wish+ # # @api internal # @see Node#to_template View::exts_of Node#provides # @author manveru def possible_exts_for(wish) pr = provides return unless engine = pr["#{wish}_handler"] View.exts_of(engine).map{|e_ext| [[*wish].map{|w_ext| /#{w_ext}\.#{e_ext}$/ }, /#{e_ext}$/] }.flatten end # For compatibility with new Kernel#binding behaviour in 1.9 # # @return [Binding] binding of the instance being rendered. # @see Action#binding # @author manveru def binding; super end # make sure this is an Array and a new instance so modification on the # wrapping array doesn't affect the original option. # [*arr].object_id == arr.object_id if arr is an Array # # @return [Array] list of root directories # # @api external # @author manveru def root_mappings [*options.roots].flatten end # Set the paths for lookup below the Innate.options.views paths. # # @param [String, Array] locations # Any number of strings indicating the paths where view templates may be # located, relative to Innate.options.roots/Innate.options.views # # @return [Node] self # # @api external # @see {Node#view_mappings} # @author manveru def map_views(*locations) trait :views => locations.flatten.uniq self end # Combine Innate.options.views with either the `ancestral_trait[:views]` # or the {Node#mapping} if the trait yields an empty Array. # # @return [Array, Array>] # # @api external # @see {Node#map_views} # @author manveru def view_mappings paths = [*ancestral_trait[:views]] paths = [mapping] if paths.empty? [[*options.views].flatten, [*paths].flatten] end # Set the paths for lookup below the Innate.options.layouts paths. # # @param [String, Array] locations # Any number of strings indicating the paths where layout templates may # be located, relative to Innate.options.roots/Innate.options.layouts # # @return [Node] self # # @api external # @see {Node#layout_mappings} # @author manveru def map_layouts(*locations) trait :layouts => locations.flatten.uniq self end # Combine Innate.options.layouts with either the `ancestral_trait[:layouts]` # or the {Node#mapping} if the trait yields an empty Array. # # @return [Array, Array>] # # @api external # @see {Node#map_layouts} # @author manveru def layout_mappings paths = [*ancestral_trait[:layouts]] paths = ['/'] if paths.empty? [[*options.layouts].flatten, [*paths].flatten] end def options Innate.options end # Whether an {Action} can be built without a method. # # The default is to allow actions that use only a view template, but you # might want to turn this on, for example if you have partials in your view # directories. # # @example turning needs_method? on # # class Foo # Innate.node('/') # end # # Foo.needs_method? # => true # Foo.trait :needs_method => false # Foo.needs_method? # => false # # @return [true, false] (false) # # @api external # @see {Node#fill_action} # @author manveru def needs_method? ancestral_trait[:needs_method] end # This will return true if the only provides set are by # {Innate::Node.included}. # # The reasoning behind this is to determine whether the user has touched # the provides at all, in which case we will not override the provides in # subclasses. # # @return [true, false] (false) # # @api internal # @see {Node::included} # @author manveru def provide_set? ancestral_trait[:provide_set] end end module SingletonMethods # Convenience method to include the Node module into +node+ and map to a # +location+. # # @param [#to_s] location where the node is mapped to # @param [Node, nil] node the class that will be a node, will try to # look it up if not given # # @return [Class, Module] the node argument or detected class will be # returned # # @api external # @see SingletonMethods::node_from_backtrace # @author manveru def node(location, node = nil) node ||= node_from_backtrace(caller) node.__send__(:include, Node) node.map(location) node end # Cheap hack that works reasonably well to avoid passing self all the time # to Innate::node # We simply search the file that Innate::node was called in for the first # class definition above the line that Innate::node was called and look up # the constant. # If there are any problems with this (filenames containing ':' or # metaprogramming) just pass the node parameter explicitly to Innate::node # # @param [Array, #[]] backtrace # # @return [Class, Module] # # @api internal # @see SingletonMethods::node # @author manveru def node_from_backtrace(backtrace) filename, lineno = backtrace[0].split(':', 2) regexp = /^\s*class\s+(\S+)/ File.readlines(filename)[0..lineno.to_i].reverse.find{|ln| ln =~ regexp } const_get($1) end end end innate-2013.02.21/lib/innate/spec.rb0000644000004100000410000000003412166103251016705 0ustar www-datawww-datarequire 'innate/spec/bacon' innate-2013.02.21/.rvmrc0000644000004100000410000000012212166103251014532 0ustar www-datawww-datarvm --install --create use 1.9.3@innate [[ -s .gems ]] && rvm gemset import .gems