Call task more than once in Rails 3 generator
Asked Answered
S

5

10

I'm writing a Rails 3 generator that creates two different models. Here's a very simplified example of what I'm trying to do:

def my_generator_task
  invoke "model", ["foo"]
  invoke "model", ["bar"]
end

The problem is that the Thor invoke method only invokes a task once, so the second call to the "model" task never happens and the "bar" model is never created. Does anyone know an elegant way to accomplish this, preferably in a way that doesn't break the ability to run "rails destroy" with the generator?

Straddle answered 2/12, 2010 at 2:58 Comment(1)
See also: #46370531Regularly
O
3

One more thought, this way it is also possible to run multiple model generator without migration

Rails::Generators.invoke("active_record:model", ["foo", "--no-migration" ])
Rails::Generators.invoke("active_record:model", ["bar", "--no-migration" ])
Owings answered 3/5, 2011 at 7:2 Comment(0)
Z
2

With Thor, if you want to invoke a task withOUT dependency management, you just call it directly:

model(foo)
model(bar
Zionism answered 5/2, 2011 at 7:17 Comment(0)
I
1

In case you want to run a generator that subclasses from Thor::Group, i.e. not just a single Thor task, you can invoke an entire generator from any different file.

Rails::Generators.invoke("my_generator", my_generator_args)

The generators module generators.rb in railties/rails seems to create a new instance, so it doesn't think that the task has already been called. This means you can repeat the above line as many times as you want and it will run each time.

Ignaz answered 23/2, 2011 at 23:51 Comment(0)
A
1

I don't know of an elegant way to do that. In this talk, I gave an example of a custom generator that invokes the controller generator twice - check out slide 43.

The inelegant way is to go into Thor's @_invocations array and delete the first run's tasks before running it again.

Adi answered 23/2, 2011 at 23:57 Comment(1)
+1 - after invoke :method, [arguments], options use @_invocations.first[1].pop to remove the most recently invoked task from the invocation list.Schwenk
D
0

there is a macro method called "behavior" can help(using bonyiii's example):

def generate_model
  if behavior == :invoke
    Rails::Generators.invoke("active_record:model", ["foo", "--no-migration"], behavior: behavior)
    Rails::Generators.invoke("active_record:model", ["bar", "--no-migration"], behavior: behavior)
  else # behavior == :revoke
    Rails::Generators.invoke("active_record:model", ["foo", "--no-migration"], behavior: :revoke)
    Rails::Generators.invoke("active_record:model", ["bar", "--no-migration"], behavior: :revoke)
  end
end

or just:

def generate_model
  Rails::Generators.invoke("active_record:model", ["foo", "--no-migration"], behavior: behavior)
  Rails::Generators.invoke("active_record:model", ["bar", "--no-migration"], behavior: behavior)
end
Delouse answered 29/7, 2013 at 10:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.