FTP file upload with custom port number in Rails

Its quite weird that I’ve never come across a scenario task that needed the involvement of FTP, at least as far as Rails is concerned. In this case, it involved a FTP PUSH whereby the application was to upload a file to a remote FTP Server. Its pretty simple:

ftp=Net::FTP.new
 ftp.passive = true
 ftp.connect("URL","PORT")
 ftp.login("USERNAME", "PASSWORD")
 ftp.putbinaryfile("/PATH/TO/FILE")
 ftp.close

In most cases, the port number defaults to 21 and hence you can use the open method instead of connect:

Net::FTP.open('URL') do |ftp|
 ftp.passive = true
 ftp.login('USERNAME', 'PASSWORD')
 ftp.putbinaryfile("/PATH/TO/FILE")

end

But in my case, the FTP server had a different command port hence had to use the connect method.  The other thing that’s worth mentioning is the passive flag. Rails sends files via FTP in active mode by default. In active mode, the server initiates a connection from its command port to the client through a random port (in the client). This method has issues because firewalls block the TCP connection from the server to the client.

In passive mode however, the client initiates both connections to the server, solving the problem of firewalls filtering the incoming data port connection to the client from the server.

Cheers!

attr_accessible and attr_protected in the Model

This is a word for word copy-paste from an answer to a question on StackOverflow. The first time I had issues with attr_accessible (which was the fact that I was missing the mass assignment bit), my thoughts were quelled by this excellent explanation. I just came across it accidentally today and thought that I should post it here.. even for my own sake.

Source: http://stackoverflow.com/questions/2652907/what-is-difference-between-attr-accessibleattributes-attr-protectedattrib

 

attr_accessible (documentation) says “the specified attributes are accessible and all others are protected” (think of it as whitelisting.)

whereas

attr_protected (documentation) says “the specified attributes are protected and all others are accessible” (think of it as blacklisting.)

protected attribute is one that can only be modified explicitly (e.g. via attribute=) and can’t be updated via mass assignment (e.g. using model.update_attributes or by passing attributes to new). Attempts to update protected attributes via mass assignment are silently ignored without raising an exception.

The classic example would be if a User model had an is_admin attribute you could protect that attribute to prevent form submissions that would allow any user to be set as an administrator.

Example:

class User < ActiveRecord::Base
# explicitly protect is_admin, any new attributes added to the model
# in future will be unprotected so we need to remember to come back
# and add any other sensitive attributes here in the future
attr_protected :is_admin
end

compared with:

class User < ActiveRecord::Base
# explicitly unprotect name and bio, any new attributes added to the model
# in the future will need to be listed here if we want them to be accessible
attr_accessible :name, :bio
end

Now, assuming is_admin attribute is protected:

> u = User.find_by_name('mikej')
> u.is_admin?
false
> u.update_attributes(:name => 'new name', :is_admin => true)
> u.is_admin?
false
> u.name
"new name" 
> u.is_admin = true # setting it explicitly
> u.save
> u.is_admin?
true









“File not found: lib” error while installing Rails 3.0.7

I was installing Rails 3.0.7 on my local machine yesterday and on a server today. I came across the same error both times:

This is the problematic part:

File not found: lib
ERROR:  While generating documentation for rails-3.0.7
... MESSAGE:   exit
... RDOC args: --ri --op /usr/local/rvm/gems/ruby-1.8.7-p334/doc/rails-3.0.7/ri lib --title rails-3.0.7 Documentation --quiet

Rails installed successfully but the Rdoc and ri documentation failed with this error. I ignored it in my local machine since I was in a hurry and Rdoc/ri were the least of my worries. But when it hapenned again in the server I just had to find out what the issue was. If you google it, many sources advise you to just uninstall that Rails version (in my case 3.0.7) and do this:

sudo gem install rails –no-ri –no-rdoc

I find that to be plain stupid! You are running away from the problem rather than solving it. The above command would just ignore the Rdoc/ri documentation.

The issue is that the new Rails version you are installing uses a more recent version of Rdoc/ri and thus when the installation process gets to Rdoc/ri installation, it fails. I don’t know why the ROR developers didn’t think of checking for this and updating Rdoc/ri for you. Anyway, the correct way to solve this issue is to first uninstall the Rails version you just installed with no Rdoc/ri data:

sudo gem uninstall rails –version 3.0.7

Install the latest version of the rdoc-data gem. This will install ri data for core and stdlib:

gem install rdoc-data

Then run:

rdoc-data –install

In case you want rdoc-data for all your gems run (not necessary.. takes a while if you have as many gems as i do):

gem rdoc –all –overwrite

To install ri data for RDoc 2.5+ run:

rdoc-data

Now you can install your Rails version and it will successfully install all the rdoc-data too.

sudo gem install rails

Output:

Successfully installed rails-3.0.7
1 gem installed
Installing ri documentation for rails-3.0.7...
Installing RDoc documentation for rails-3.0.7...

Getting the current action and controller from the view in Rails

This turned out to be quite simple. You might need it for a myriad of reasons at which point the dirty alternative (at least in rails) would be to do some URL parsing. I got a clean solution from the following post:

http://www.postal-code.com/mrhappy/blog/2007/01/18/rails-knowing-the-current-action-in-a-view/

If you add the following code to your application_controller.rb,

private

before_filter :instantiate_controller_and_action_names

def instantiate_controller_and_action_names

@current_action = action_name

@current_controller = controller_name

end

You will have access to the instance variables that represent the action and the controller. Pretty neat ay?

The above solution is for me the neatest one since it promotes DRY code.

The second solution is just using the controller keyword to access the values of the action and the controller right in your view:-

controller.controller_name

controller.action_name

P.S I was working with Rails 2.3 at the time

Getting the current URI (Everything AFTER the domain)

This is just a mini post of a simple thing that I might either way forget in future. So if you want to get the URI of the current page and what’s relevant to you is everything after the domain, try this:-

request.request_uri

In a URI like lets say http://www.mysite.com/downloads&#8230; it will return /downloads

A practical example of how I used it in a Rails app is here. Cheers!

&lt;% if request.request_uri.eql?(root_path) %&gt; cssnav_visited&lt;% end %&gt;”&gt;Home

Getting rid of periods using Rails’ validates_format_of validation method

I just love the validation methods in Rails! They make life so much easier. Here’s how I checked that the file being uploaded to a server does not have periods(Long story… The title was ending up being a link to the download and thus the resultant URL messed up with the routing. Encoding the URL proved trickier than expected in this particular instance. If you have any insights on the encoding give me a shout on the comments).

validates_format_of         :title , :with =&gt; /\A[^.]*\Z/, :message =&gt; “cannot have periods(.)”

Cheers!

P.S This was in Rails 2.3

Matching all occurrences of a regex

This was a bit stupid of me. So I’m blogging about it to avoid being this stupid again. I was working on my own little Rack middleware and i needed to get the contents of the url after the domain name i.e get the bolded strings here: http://www.pissoff.com/yes/why/dont/ya. I had the regex working ok and it was working on Rubular though  it wasn’t showing the matches i.e it was highlighting them but not listing them down as it should do usually. Here is the regex:

/[^\/]+/

The problem is I was using the Regexp class to match it and this was only producing the first match and returning all others as nil. Maybe I was using it in the wrong way, I don’t know. What I’m certain of is the fact that the String class worked much better.

So in a nutshell, I used the String class’ scan method to get all my matches as shown below:

url = “/admin/product/show/012”
url.scan(/[^\/]+/) { |match|
puts match
}

OUTPUT

admin
product
show
012