assigning lifecycle states on creation

52 views
Skip to first unread message

Jim Harvey

unread,
Sep 26, 2011, 4:23:35 PM9/26/11
to hobo...@googlegroups.com
I have the following in user.rb:

lifecycle do
  state :active, :default => true
  state :inactive
  state :invited

  ... some custom creators and transitions ...
end

First of all, whenever I create a new user using the "new user" form, the state is set to inactive. Any ideas why? The default used to be "inactive" but I clearly changed the code to what is shown above. 

Also, I'd like to have a checkbox input on the "new user" form that sets the state to active or inactive (along with taking some other actions) depending on whether the box is checked. I was trying to use a before_filter on the create action to set the state, etc. but I'm not sure how to access the User. For example, @user is nil. My current understanding is that a new User is instantiated with the state already set when the "new form" is loaded.

If it's unclear what I'm trying to do or if more detail is needed, please let me know. I appreciate any insight, as usual - I'm still pretty new at this. Thanks, 

Jim



kevinpfromnm

unread,
Sep 26, 2011, 4:47:51 PM9/26/11
to hobo...@googlegroups.com
Have you run a new migration since making that change?  I believe it works via db default.

For the other, I'd probably make a new lifecycle create that has state as a param

Jim Harvey

unread,
Sep 26, 2011, 5:44:48 PM9/26/11
to hobo...@googlegroups.com
Thanks Kevin - I hadn't run a migration so I'm sure that was the problem, good to know. I'll try writing another custom creator. Thanks for the advice!

Jim Harvey

unread,
Sep 28, 2011, 1:55:20 PM9/28/11
to hobo...@googlegroups.com
I'm still struggling with the second part of my original post. Here is, basically, what I need to accomplish:

1. Admin can create a new user with default state set to :active (easy)
2. Admin can check a box on the *same new user form* to set the new user's state to :inactive and send the user an activation email instead. (having trouble)

I don't want to write a new "creator" in my lifecycle because I want to use the default "new user" form with its many existing fields. I don't want to specify everything in :params and then have to update it every time a new field is added to the user model. Also, I read in the manual that I can use a Proc with the :become option but I can't access the params hash (with my custom checkbox state) in the model to decide which state to "become". Lastly, if I try to set the lifecycle state as one of the :params for the creator, it still doesn't show up in the form.

In the controller, if I try to add some logic based on whether or not my checkbox is checked, I still can't seem to set the state directly to :inactive on the user, then send an email. But if I create a lifecycle transition to take care of that, I'm not sure how to (or if I can?) call it from the controller. 

If I'm going about this all wrong or if anyone has any other ideas, I'd be most grateful. Thanks again!

kevinpfromnm

unread,
Sep 28, 2011, 2:56:29 PM9/28/11
to hobo...@googlegroups.com
Here's a simple way to avoid having to specify all the params.

    User.columns.*.name - %w{created_at updated_at crypted_password key_timestamp remember_token remember_token_expires_at salt}

Somewhat ugly but should work.  Then you can either make two creators (one invite, one new), or...
make one, make an attr (not a field) to hold the state destination, have the attr in the params, add logic to the block or to the become proc to set it and have a test as to what email or whether to send an email at all in the create block.

I'd recommend the first option.

Jim Harvey

unread,
Sep 28, 2011, 4:45:47 PM9/28/11
to hobo...@googlegroups.com
Thanks Kevin - In theory, I don't have a problem with two new creators. However, the DRYML <tag=form for=User> is extended and heavily customized in admin_site.dryml. If I define two new creators in user.rb then I get a two new polymorphic form tag definitions automatically created that don't reference my extension. What I really want is for the params defined in the extension (as fields in the field-list), along with all the other modifications, to influence the forms for the new lifecycle creators. Is there a way to do that?  

kevinpfromnm

unread,
Sep 28, 2011, 5:05:33 PM9/28/11
to hobo...@googlegroups.com
You can make a base form and use it with each lifecycle create action.  Just make sure that the action is linked correctly (where the form submits).  See taglibs/auto/rapid/forms.dryml for the auto defined version as an starting example.

The default lifecycle form will have an input for each of the params (whatever is standard for the field type) and nothing else aside from a few hidden inputs.

Matt Jones

unread,
Sep 28, 2011, 6:37:26 PM9/28/11
to hobo...@googlegroups.com

On Sep 26, 2011, at 4:23 PM, Jim Harvey wrote:

> I have the following in user.rb:
>
> lifecycle do
> state :active, :default => true
> state :inactive
> state :invited
>
> ... some custom creators and transitions ...
> end
>

[snip - default question already answered]

> Also, I'd like to have a checkbox input on the "new user" form that sets the state to active or inactive (along with taking some other actions) depending on whether the box is checked. I was trying to use a before_filter on the create action to set the state, etc. but I'm not sure how to access the User. For example, @user is nil. My current understanding is that a new User is instantiated with the state already set when the "new form" is loaded.

I suspect the lifecycle creators are probably not the best path for this, since you really only want one form. The standard vanilla-Rails way to do this is with attr_accessor for the checkbox (in user.rb):

attr_accessor :send_activation, :type => :boolean

You'll need to add the field to your field-list on the 'new' page, but given that it's customized that shouldn't be an issue.

Then, in a model callback (again in user.rb), do something like:

before_validation :set_user_state, :on => :create

def set_user_state
self.state = 'inactive' if send_activation
end

This will override the default state as needed. I used before_validation because it's frequently the case that some user validations might be checking it, and setting it in before_create or before_save will be too late.

Then, to actually handle sending the email, use an after_create callback (or an observer) to fire off the activation email.

--Matt Jones

Reply all
Reply to author
Forward
0 new messages