Class: Innate::Action

Inherits:
Struct
  • Object
show all
Defined in:
lib/innate/action.rb

Constant Summary collapse

COPY_VARIABLES =
'
STATE[:action_variables].each do |iv, value|
  instance_variable_set("@#{iv}", value)
end'.strip.freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.create(hash = {}) ⇒ Action

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.

Parameters:

  • hash (Hash, #to_hash) (defaults to: {})

    used to seed new Action instance

Returns:

  • (Action)

    action with the given defaults from hash

Author:

  • manveru



15
16
17
18
# File 'lib/innate/action.rb', line 15

def self.create(hash = {})
  default = {:options => {}, :variables => {}, :params => []}
  new(*default.merge(hash.to_hash).values_at(*ACTION_MEMBERS))
end

Instance Method Details

#bindingBinding

Returns binding of the instance for this Action.

Returns:

  • (Binding)

    binding of the instance for this Action

See Also:

Author:

  • manveru



45
46
47
# File 'lib/innate/action.rb', line 45

def binding
  instance.binding
end

#callString

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

Returns:

  • (String)

    The rendition of all nested calls

See Also:

Author:

  • manveru



34
35
36
37
38
39
# File 'lib/innate/action.rb', line 34

def call
  Current.actions << self
  render
ensure
  Current.actions.delete(self)
end

#copy_variables(binding = self.binding) ⇒ NilClass

Copy Action#variables as instance variables into the given binding.

This relies on Innate::STATE, so should be thread-safe and doesn’t depend on Innate::Current::actions order. So we avoid nasty business with Objectspace#_id2ref which may not work on all ruby implementations and seems to cause other problems as well.

Parameters:

  • binding (Binding #eval) (defaults to: self.binding)

Returns:

  • (NilClass)

    there is no indication of failure or success

See Also:

  • View::ERB::render

Author:

  • manveru



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/innate/action.rb', line 86

def copy_variables(binding = self.binding)
  return unless variables.any?

  STATE.sync do
    STATE[:action_variables] = self.variables

    eval(COPY_VARIABLES, binding)

    STATE[:action_variables] = nil
  end
end

#layout_view_or_method(name, arg) ⇒ Object



127
128
129
# File 'lib/innate/action.rb', line 127

def layout_view_or_method(name, arg)
  [:layout, :view].include?(name) ? [arg, nil] : [nil, arg]
end

#merge!(hash) ⇒ Object



20
21
22
23
# File 'lib/innate/action.rb', line 20

def merge!(hash)
  hash.each_pair{|key, value| send("#{key}=", value) }
  self
end

#nameObject

Try to figure out a sane name for current action.



132
133
134
# File 'lib/innate/action.rb', line 132

def name
  File.basename((method || view).to_s).split('.').first
end

#renderObject



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/innate/action.rb', line 98

def render
  self.instance = node.new
  self.variables[:content] ||= nil

  instance.wrap_action_call(self) do
    copy_variables # this might need another position after all
    self.value = instance.__send__(method, *params) if method
    self.view_value = File.read(view) if view

    body, content_type = wrap_in_layout{
      engine.call(self, view_value || value || '') }
    options[:content_type] ||= content_type if content_type
    body
  end
end

#sync_variables(from_action) ⇒ Action

Copy the instance variable names and values from given from_action#instance into the Action#variables of the action this method is called on.

Parameters:

  • from_action (Action #instance)

Returns:

See Also:

Author:

  • manveru



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/innate/action.rb', line 58

def sync_variables(from_action)
  instance = from_action.instance

  instance.instance_variables.each{|iv|
    iv_value = instance.instance_variable_get(iv)
    iv_name = iv.to_s[1..-1]
    self.variables[iv_name.to_sym] = iv_value
  }

  from_action
end

#valid?Boolean

Returns:

  • (Boolean)


136
137
138
# File 'lib/innate/action.rb', line 136

def valid?
  method || view
end

#wrap_in_layoutObject



114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/innate/action.rb', line 114

def wrap_in_layout
  return yield unless layout

  action = dup
  action.view, action.method = layout_view_or_method(*layout)
  action.layout = nil
  action.view_value = nil
  action.sync_variables(self)
  body, content_type = yield
  action.variables[:content] = body
  return action.call, content_type
end