Class: Scheherazade::Story
- Inherits:
-
Hash
- Object
- Hash
- Scheherazade::Story
- Extended by:
- ClassMethods
- Defined in:
- lib/scheherazade/story.rb
Defined Under Namespace
Modules: ClassMethods
Constant Summary collapse
- TOP =
new(nil)
Instance Attribute Summary collapse
-
#characters ⇒ Object
readonly
Returns the value of attribute characters.
-
#counter ⇒ Object
readonly
Returns the value of attribute counter.
-
#current ⇒ Object
readonly
Returns the value of attribute current.
-
#fill_attributes ⇒ Object
readonly
Returns the value of attribute fill_attributes.
Instance Method Summary collapse
- #after_imagine(&block) ⇒ Object
- #fill(character_or_model, *with) ⇒ Object
- #get(character) ⇒ Object
-
#imagine(character_or_model, attributes = nil) ⇒ Object
Creates a character with the given attributes.
-
#initialize(parent = self.class.current) ⇒ Story
constructor
A new instance of Story.
-
#with(temp_current) ⇒ Object
Allows one to temporarily override the current characters while the given block executes.
Methods included from ClassMethods
begin, end, tell, to_character, to_character!, to_model
Constructor Details
#initialize(parent = self.class.current) ⇒ Story
Returns a new instance of Story.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/scheherazade/story.rb', line 59 def initialize(parent = self.class.current) super(){|h, k| parent[k] if parent } @parent = parent @current = Hash.new do |h, k| if (char = to_character!(k)) h[char] else parent.current[k] if parent end end @fill_attributes = Hash.new{|h, k| parent.fill_attributes[k] if parent } @characters = Hash.new {|h, k| parent.characters[k] if parent } @counter = parent ? parent.counter.dup : Hash.new(0) @filling = [] @after_imagine = {} @built = [] end |
Instance Attribute Details
#characters ⇒ Object (readonly)
Returns the value of attribute characters.
3 4 5 |
# File 'lib/scheherazade/story.rb', line 3 def characters @characters end |
#counter ⇒ Object (readonly)
Returns the value of attribute counter.
3 4 5 |
# File 'lib/scheherazade/story.rb', line 3 def counter @counter end |
#current ⇒ Object (readonly)
Returns the value of attribute current.
3 4 5 |
# File 'lib/scheherazade/story.rb', line 3 def current @current end |
#fill_attributes ⇒ Object (readonly)
Returns the value of attribute fill_attributes.
3 4 5 |
# File 'lib/scheherazade/story.rb', line 3 def fill_attributes @fill_attributes end |
Instance Method Details
#after_imagine(&block) ⇒ Object
158 159 160 161 |
# File 'lib/scheherazade/story.rb', line 158 def after_imagine(&block) raise NotImplementedError unless model = to_model(current_fill) @after_imagine[model] = block end |
#fill(character_or_model, *with) ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/scheherazade/story.rb', line 146 def fill(character_or_model, *with) char = to_character(character_or_model) fill_attributes[char] = with @characters[char] = current_fill unless to_model(char) begin @filling.push(char) yield ensure @filling.pop end if block_given? end |
#get(character) ⇒ Object
130 131 132 |
# File 'lib/scheherazade/story.rb', line 130 def get(character) current[character] || imagine(character) end |
#imagine(character_or_model, attributes = nil) ⇒ Object
Creates a character with the given attributes
A character can be designated either by the model (e.g. ‘User`), the corresponding symbol (`:user`) or the symbol for a specialized type of character, defined using fill
(e.g. `:admin`).
The attributes can be nil, a list of symbols, a hash or a combination of both These, along with attributes passed to fill
for the current stories and the mandatory attributes for the model will be provided.
If some fields generate validation errors, they will be provided also.
For associations, the values can also be a character (Symbol or Model), integers (meaning the default Model * that integer) or arrays of characters.
imagine(:user, :account, :company => :fortune_500_company, :emails => 3)
Similarly:
User.imagine(...)
:user.imagine(...)
This record (and any other imagined through associations) will become the current character in the current story:
story.current[User] # => nil
story.tell do
:admin.imagine # => A User record
story.current[:admin] # => same
story.current[User] # => same
end
story.current[User] # => nil
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/scheherazade/story.rb', line 112 def imagine(character_or_model, attributes = nil) character = to_character(character_or_model) prev, @building = @building, [] # because method might be re-entrant CharacterBuilder.new(character).build(attributes) do |ar| ar.save! # While errors on records associated with :has_many will prevent records # from being saved, they won't for :belongs_to, so: @building.each do |ar| ar.valid? and raise ActiveRecord::RecordInvalid, ar.errors unless ar.persisted? end Scheherazade.log(:saving, character, ar) handle_callbacks(@building) end ensure @built.concat(@building) @building = prev end |
#with(temp_current) ⇒ Object
Allows one to temporarily override the current characters while the given block executes
137 138 139 140 141 142 143 144 |
# File 'lib/scheherazade/story.rb', line 137 def with(temp_current) keys = temp_current.keys.map{|k| to_character(k)} previous_values = current.values_at(*keys) current.merge!(Hash[keys.zip(temp_current.values)]) yield ensure current.merge!(Hash[keys.zip(previous_values)]) end |