How do I create a function

Can someone explain to me how I create a function in ROR, where put it
and
how I access it? Do I just create another action? What is the correct
way to do this? Any help would be appreciated.

Jason

Jason H. wrote in post #961994:

Can someone explain to me how I create a function in ROR,

By learning Ruby.

where put it
and
how I access it? Do I just create another action? What is the correct
way to do this?

That depends on what you’re trying to achieve.

Any help would be appreciated.

Help: go learn Ruby.

Jason

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Sent from my iPhone

Marnen,

That was absolutely no help.

Thanks anyways.

Jason

On Tue, Nov 16, 2010 at 8:12 PM, Jason H. [email protected] wrote:

Marnen,

That was absolutely no help.

Your question is very vague, and there is a lot of information available
online… if you google ‘ruby function’ you will find this link, which
gives
an answer as broad as your question:
http://www.howtogeek.com/howto/programming/ruby/ruby-function-method-syntax/

Along with other links.

If you want more specifics please give them, we are not mind readers
(most
of us) - i.e. what are you doing… creating a new controller action? A
function in a model? A helper? Did you create a Rails app? Do you have
Rails
installed? Do you have Ruby installed?

I have a rails app. I understand how to create a function in Rails.

I have a contact that is viewable by multiple users. I want to create a
function to lock and unlock the contact. I have a field in the contact
database called locked.

I assume I create a new function in the action controller or contact
controller like:

def lock(contact_id)
c=Contact.find(contact_id)
c.locked = 1
c.save
end

def unlock(contact_id)
c=Contact.find(contact_id)
c.locked = 0
c.save
end

Is this the proper way to do this? How do I make sure it’s not
accessible through the through the URL: /Contacts/lock?

On Tue, Nov 16, 2010 at 9:48 PM, Jason H. [email protected] wrote:

c=Contact.find(contact_id)

Is this the proper way to do this? How do I make sure it’s not
accessible through the through the URL: /Contacts/lock?

By keeping the function out of the controller. You may either place
lock and unlock in a helper file, or make them as a part of the model
itself. I, personally, vote for the latter. Rule of thumb: smart
models, thin controller.

Happy hacking!

Thanks Brian!

Just to hopefully elaborate on things a bit here to help you out Jason

In Ruby, since it’s literally a pure Object Oriented language,
generally you’ll see functions referred to instead as “methods”. Same
thing basically, just a nomenclature difference that could make things
easier in the future if you know about it :slight_smile:

Brian has a good suggestion in terms of design - that kind of
functionality should belong in the model. However, there are some
simpler ways to do things, but it depends largely on how you have your
application set up.

As you’re probably already aware, you can update your contact model
from within your controller like this:

def update
@contact = Contact.find(params[:id])
@contact.update_attributes(params[:contact])
end

This means you can pass in the “locked” flag in your form. However,
depending on how your application is set up, this COULD pose a
security risk. In Rails, there’s a way to protect certain attributes
on a model from being set by a simple form:

class Contact < ActiveRecord::Base
attr_protected :locked
end

The attr_protected method will basically refuse to assign any value to
the attributes it’s protecting if those values come out of a form or a
mass update (see “mass assignment” - Railscasts.com has a screencast
on it, if memory serves).

So the question then becomes, how do you securely update the locked
attribute? One way you could do it would be by adding a controller
action called “lock” and/or “unlock”, but instead of allowing the
controller to do the work, call a new method you create on your
model. Here’s an example:

class ContactsController < ActionController
def index
# …
end

def show
# …
end

def lock
@contact = Contact.find(params[:id])
if current_user.contacts.include?(@contact)
@contact.lock
end
end

def unlock
@contact = Contact.find(params[:id])
if current_user.contacts.include?(@contact)
@contact.unlock
end
end
end

class Contact < ActiveRecord::Base

… all your current model stuff

def lock
self.update_attribute(:locked, true)
end

def unlock
self.update_attribute(:locked, false)
end
end

To elaborate, the controller basically implements two new “actions” -
lock and unlock. Inside each, it looks for a current_user object
(this assumes your application has some form of authentication set up)
and says, “does current_user’s contacts include the contact object we
just looked up in the database?” If so, the lock or unlock method is
called on that contact. If not, nothing happens. This effectively
makes sure that your contact is only updated by the user who owns it.

I recognize that this may seem a little like “beating around the bush”
in regards to your original question, so take a look at the lock and
unlock methods that I put in the contact class above. Generally
speaking, Brian’s mentioned rule of thumb, which I’ve always heard
stated as “skinny controller, fat model”, is the way to go. The basic
idea is to push as much functionality down to the model level as
possible, and allow your controllers to be as generic and lean as
possible. This is useful for situations where you may not want to
actually go through the controller - like, for example, using the
Rails console.

Anyway, these two methods just update the locked attribute to be
either true or false. In Ruby, it’s a generally accepted “design
pattern” to create lots of small, short methods to do a few basic
things at a time. It’s not uncommon at all to see lots of methods
that are only a few lines like this, that just set one or more
attributes at a time, possibly performing some form of custom
validation(s) along the way.

Hopefully this example helps you wrap your head around the situation a
little better. Good luck to you!

On 17 November 2010 01:24, Jason H. [email protected] wrote:

Can someone explain to me how I create a function in ROR

On 17 November 2010 02:48, Jason H. [email protected] wrote:

I have a rails app. I understand how to create a function in Rails.

I’m a little confused as to what you need, as these two posts seem to
be contradictory.

I agree with the sentiment of Marnen’s post; if you’re confused at
this stage about how to structure your code in Ruby (hint, there’s
very little difference in general terms with any other OO language -
differences in idiom, syntax and some functionality, sure - but if you
know Java or C#, you should be able to understand a Ruby class easy
enough. My point here is that your question possibly seems to be
partly about OO programming generally, not Rails specifically) or how
to organise the structure of a Rails application, then there are some
very good primers out there on the WWW, and several highly recommended
books on the subject too.

On 17 November 2010 02:48, Jason H. [email protected] wrote:

Is this the proper way to do this? How do I make sure it’s not
accessible through the through the URL: /Contacts/lock?

I see you now already have a couple of suggestions, and I’ll add the
“private” keyword to the mix as another alternative… they’re all
choices, but I would prefer the approach of utilising methods on the
model.

PS Please try not to top-post your replies, but to interleave them
with appropriate quotes, to make following the conversation as easy as
possible for readers.

Regards

Jason H. wrote:

c=Contact.find(contact_id)

Is this the proper way to do this? How do I make sure it’s not
accessible through the through the URL: /Contacts/lock?

You can create a ‘private’ section in your controller if you have
something which belongs in the controller. The stuff in private is
accessable from methods in the controller but not through the url.

Thanks Phoenix R. for the detailed explanation. This is just what I
needed. Much appreciated! I am understanding Rails more and more every
day.