class MagicResource::Container

Constants

CONTEXT_PATTERNS

Attributes

changed[RW]
changed?[RW]
collection[RW]
context[R]
helper[RW]
item[RW]
name[RW]
resource[R]
resources[R]
rs[R]

Public Class Methods

_launch(helper, *args) click to toggle source
# File lib/magic-resource/container.rb, line 171
def self._launch(helper, *args)
  args.present? ?
    self.new(args.first)._launch(helper, true) :
    # Let's try to keep resource_container to be private..
    helper.send(:resource_container)._launch(helper)
end
new(rs, context = nil) click to toggle source
# File lib/magic-resource/container.rb, line 185
def initialize(rs, context = nil)
  rs = rs.object if rs.respond_to?(:object)
  self.rs, self.context = rs, context
end

Private Class Methods

resource_name(duck) click to toggle source
# File lib/magic-resource/container.rb, line 246
def self.resource_name(duck)
  raise 'Undefined resource name' if duck.nil?
  return duck if duck.kind_of?(Symbol)
  return duck.to_sym if duck.kind_of?(String)
  return duck.model_name.route_key.to_sym if duck.respond_to?(:model_name)
  return resource_name(duck.klass) if duck.respond_to?(:klass)
  return resource_name(duck.class) unless duck.kind_of?(Class)
  duck.name.underscore.pluralize.to_sym
end

Public Instance Methods

_launch(helper, changed = false) click to toggle source
# File lib/magic-resource/container.rb, line 165
def _launch(helper, changed = false)
  self.helper = helper
  self.changed = changed
  self
end
content(index) click to toggle source
# File lib/magic-resource/container.rb, line 154
def content(index)
  MagicResource.assert_restriction(
    :disable_content_for_helper,
    "`#content helper is too much magical...: #{index}"
  )

  index = extract_context(index, :content)

  helper.resource_contents[rs].try(:[], index)
end
content_for(index, *args, &block) click to toggle source
# File lib/magic-resource/container.rb, line 134
def content_for(index, *args, &block)
  MagicResource.assert_restriction(
    :disable_content_for_helper,
    "#content_for helper is too much magical...: #{index}"
  )

  content = if block_given?
    raise ArgumentError.new("Both content param and block specified: #{index}") if args.present?
    helper.capture(&block)
  else
    raise ArgumentError.new("Need to specify the content by second param or block: #{index}") unless args.present?
    args.first
  end

  index = extract_context(index, :content)

  helper.resource_contents[rs] ||= {}
  helper.resource_contents[rs][index] = content
end
context?(*args) click to toggle source
# File lib/magic-resource/container.rb, line 20
def context?(*args)
  args.include?(context)
end
form_for(action, *args, &block) click to toggle source
# File lib/magic-resource/container.rb, line 118
def form_for(action, *args, &block)
  options = args.extract_options!
  form_type = args.shift

  action, ct, route_args = extract_route_context(action)
  with_context(ct) do
    url, method = route_to(action, route_args)

    form_type ||= MagicResource.default_form_type
    form_type, obj = form_type.kind_of?(Ransack::Search) ?
      [:search, form_type] :
      [form_type, item]
    helper.public_send(:"#{form_type}_form_for", obj, {url: url, method: method}.merge(options), &block)
  end
end
path_to(action) click to toggle source

Used in controller and view

# File lib/magic-resource/container.rb, line 90
def path_to(action)
  action, ct, route_args = extract_route_context(action)
  with_context(ct) do
    route_to(action, route_args).first
  end
end
redirect_to(action, options = {}) click to toggle source

Used in controller

# File lib/magic-resource/container.rb, line 98
def redirect_to(action, options = {})
  helper.redirect_to path_to(action), options
end
render(partial, *args) click to toggle source
# File lib/magic-resource/container.rb, line 24
def render(partial, *args)
  options = args.extract_options!
  if args.present? && form = args.shift
    raise 'Form object containing wrong resource' unless form.object == rs
    options[:f] = form unless options.has_key?(:f)
  end

  partial, ct = extract_context(partial, :template)

  lookup_templates = [name, :resources].
    flat_map{|lc| ["#{lc}/#{ct}", lc] }.
    map{|l| "#{l}/#{partial}"}

  template = lookup_templates.find{|t| helper.lookup_context.template_exists?(t, [], true)}
  raise("Can't find #{lookup_templates[0]} template for #{name} resource") unless template

  with_context(ct){helper.with_resource_container(self){helper.render(template, options)}}
end
render_collection(partial, options = {}) click to toggle source
# File lib/magic-resource/container.rb, line 43
def render_collection(partial, options = {})
  partial, ct = extract_context(partial, :template)
  collection.map{|r| helper.r(r).render("#{name}::#{ct}/#{partial}", options)}.join.html_safe
end
render_collection_build(partial, options = {}) click to toggle source
# File lib/magic-resource/container.rb, line 63
def render_collection_build(partial, options = {})
  partial, ct = extract_context(partial, :template)
  helper.r(resources.soft_build).render("#{name}::#{ct}/#{partial}", options)
end
t(key, options = {}) click to toggle source
# File lib/magic-resource/container.rb, line 48
def t(key, options = {})
  key, ct = extract_context(key, :translation)

  lookup_keys = [name, :resources].
    flat_map{|lc| ["#{lc}.#{ct}", lc] }.
    map{|l| :"#{l}.#{key}"}

  helper.t(
    lookup_keys[0],
    options.merge(
      default: lookup_keys[1..-1] + Array.wrap(options[:default])
    )
  )
end

Private Instance Methods

context=(new_context) click to toggle source
# File lib/magic-resource/container.rb, line 203
def context=(new_context)
  @context = new_context || MagicResource.default_context
end
extract_context(pattern, context_type) click to toggle source
# File lib/magic-resource/container.rb, line 207
def extract_context(pattern, context_type)
  parse_params = CONTEXT_PATTERNS[context_type]

  pattern = pattern.to_s
  pattern.prepend(parse_params[:separator]) unless pattern.include?(parse_params[:separator])
  pattern_parts = pattern.match(parse_params[:regexp])
  raise("Wrong resource target pattern: #{pattern}") unless pattern_parts

  target_name = pattern_parts[:name].try(:to_sym)
  MagicResource.assert_restriction(
    :force_resource_name_definition,
    "Need to specify resource name when switching resource: #{pattern}"
  ) if changed? && target_name.nil?

  if target_name
    raise("Wrong resource name, expected #{name.inspect} but got #{target_name.inspect}") unless name == target_name
  end

  #Damn, string keys...
  pattern_parts.names.include?('context') ?
    [pattern_parts[:target].to_sym, pattern_parts[:context].try(:to_sym) || context] :
    pattern_parts[:target].to_sym
end
extract_route_context(action) click to toggle source
# File lib/magic-resource/container.rb, line 231
def extract_route_context(action)
  action, route_args = action.kind_of?(Hash) ? action.first : [action, {}]

  extract_context(action, :route) << route_args
end
route_to(action, route_args = {}, only_path = true) click to toggle source
# File lib/magic-resource/container.rb, line 256
def route_to(action, route_args = {}, only_path = true)
  action = (item.try(:persisted?) ? :update : :create) if action == :save

  options = helper.url_options.deep_merge(
    action: action,
    only_path: only_path,
    _recall: {
      controller: [name, context].compact.join('/'),
      # Need to confuse Rails..
      action: 'hope_not_existing_action'
    }
  ).deep_merge(route_args)

  resource.try(:persisted?) ?
    options[:_recall][:id] = resource :
    options[:_recall].delete(:id)

  url = helper._routes.url_for(options)
  [url, url.http_verb]
end
rs=(new_rs) click to toggle source
# File lib/magic-resource/container.rb, line 190
def rs=(new_rs)
  @rs, self.name = new_rs.kind_of?(Symbol) ?
    [nil, new_rs] :
    [new_rs, nil]

  self.collection, self.item = rs.respond_to?(:to_ary) ?
    [rs, nil] :
    [nil, rs]

  # Just `||=` not working due to private method
  self.name = self.name || self.class.resource_name(rs)
end
with_context(context) { || ... } click to toggle source
# File lib/magic-resource/container.rb, line 237
def with_context(context)
  same_context = self.context == context
  old_context, self.context = self.context, context unless same_context

  yield
ensure
  self.context = old_context unless same_context
end