views:

25

answers:

2

Hello, tricky problem.

I have a controller that is:

def create
.
.
@project = Project.find(params[:project]

@Log = Logs.create(params[:action]).merge(:project_id => @project.id))
...
end

The issue hereis that sometimes when DEF CREATE, I'll have a project and I want to record that. Other times I won't and that's perfectly fine, I still want to create the @Log

What's the right way in Rails to handle this. I'll want to make sure:

  • The first line @project doesn't error.
  • Also that the @log doesn't error but inserts '' or NIL whatever is rails standard.

Thank you

A: 

Create a protected method near the bottom of your controller like so:

protected

def project_id
  # return the cached value if we've already figured it out
  return @project_id if defined?(@project_id)

  # get the project by id in a failsafe way
  project = params[:project_id] ? Project.find_by_id(params[:project_id]) : nil

  # return nil if the project is nil, so we don't try to call "id" on it
  return @project_id = nil if project.nil?

  # cache and return the project id
  @project_id = project.id
end

Notice I changed the parameter to :project_id instead of just project. This fits the rails convention better. Now in your create action, and all other actions, you can call it safely:

@Log = Logs.create(params[:action]).merge(:project_id => project_id))

I hope this helps!

Jaime Bellmyer
@Jaime, very cool. But I somethings broken. Just checked my logs. I confired that the protected method is being called. But when it goes to find the project (find_by_id) it's getting an ID of NULL.... not sure if this matters or not, but since I'm getting this ID from a form, I changed it to: params[:msg][:project_id]
Just confirmed, the protected call can't get params[:msg][:project_id] it's empty
Ah ok so that's the problem yet again... params[:msg][:project_id] Does not always exist. so this is break again. hmm
That's okay, just add a conditional to the find_by_id line above, so it only checks if there *is* an id to check with. I'll update the answer above to reflect this.
Jaime Bellmyer
+1  A: 

Try this:

def create

  @project = (project_id = params[:project_id]).blank? ? nil : 
             Project.find(project_id)

  @Log = Logs.create(params[:action].merge(@project.nil? ? {} : 
             {:project_id => @project.id}))

end

If the input has a project_id, then above solution will throw an error if a project with the given id is not found. If you don't want this behavior use find_by_id instead of find.

KandadaBoggu