# Updating a page using script/runner

**URL:** <https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162>\
**Category:** Radiant CMS\
**Created:** [August 28, 2007, 9:41am UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162 "2007-08-28T09:41:22Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [August 28, 2007, 9:41am UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/1 "2007-08-28T09:41:22Z")

</div>

Dear All,

Thanks for the kind lessons on how to add a page using script/runner. I  
have the following working script to create such a new page:

# ------ start of script to add a new page —

parent = Page.find\_by\_url(’/services/news’)  
child = parent.children.build(:title =\> “Floods”,  
:breadcrumb =\> “Floods”, :slug =\> “floods”)  
child.parts.build(:content =\> “This is a page for flood news”,  
:name =\> “body”)  
child.save!

# ------ end of script to add a new page —

How may I update the contents using script/runner? I have tried  
the following, but it does not work. Any help to solve this  
would be much appreciated.

# ---- test script that does not work

floods = Page.find\_by\_url(’/services/news/floods’)  
floods.parts.build(:content =\> “This is now for droughts”)  
floods.update

thanks in advance,

saji

---

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [August 28, 2007, 3:10pm UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/2 "2007-08-28T15:10:17Z")

</div>

Saji,

You might try using “create” instead of “build”. In that case, it could  
look like this:

parent = Page.find\_by\_url(‘/services/news’)  
child = parent.children.create(:title =\> “Floods”, :breadcrumb =\>  
“Floods”, :slug =\> “floods”)  
child.parts.create(:name =\> “body”, :content =\> “This is a page for  
flood news”)

Keep in mind that create and build might not work if the collection is  
empty or the original object is unsaved [1]. Your other alternative is  
to build the objects manually, then push it into the collection:

parent = Page.find\_by\_url(‘/services/news’)  
child = Page.new(:title =\> “Floods”, :breadcrumb =\> “Floods”, :slug =\>  
“floods”)  
part = PagePart.new(:name =\> “body”, :content =\> “This is a page for  
flood news”)  
parent.children \<\< child  
child.parts \<\< part

Also note in your second snippet that your part needs a name.

Sean

[1]

> **[ActiveRecord::Associations::ClassMethods](https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#M000642)**
>
> Associations are a set of macro-like class methods for tying objects together through foreign keys.

(if I’m interpreting the doc correctly)

---

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [August 31, 2007, 6:01am UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/3 "2007-08-31T06:01:27Z")

</div>

Sean,

Thanks very much for the advice. On using “create” and then “update”,  
I found that duplicate body “parts” were being “created” every time I  
ran  
the code. So running the script 5.times resulted in 5 “body parts” for  
the  
same page. After some experiments, here is what I found to suit my  
purposes ( replacing a part of the page with new stuff). Esp. used  
the “clear” method to wipe the page parts clean

# ------------

floods=Page.find\_by\_url(‘/services/news/floods’)  
floods.parts.clear # wipe clear the flood page of its parts  
floods.parts.create(  
:content =\> “Now for floods and droughts”,  
:name =\> “body”  
)  
floods.update

# ------------

saji  
…

- Sean C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) [2007-08-28 08:09:10 -0500]:

> child.parts \<\< part
> 
> > Dear All,  
> > :name =\> “body”)  
> > floods = Page.find\_by\_url(‘/services/news/floods’)  
> > Search: [http://radiantcms.org/mailing-list/search/](http://radiantcms.org/mailing-list/search/)  
> > Site: [http://lists.radiantcms.org/mailman/listinfo/radiant](http://lists.radiantcms.org/mailman/listinfo/radiant)
> 
> * * *
> 
> Radiant mailing list  
> Post: removed\_email\_address@domain.invalid  
> Search: [http://radiantcms.org/mailing-list/search/](http://radiantcms.org/mailing-list/search/)  
> Site: [http://lists.radiantcms.org/mailman/listinfo/radiant](http://lists.radiantcms.org/mailman/listinfo/radiant)

–  
Saji N. Hameed

APEC Climate Center +82 51 668 7470  
National Pension Corporation Busan Building 12F  
Yeonsan 2-dong, Yeonje-gu, BUSAN 611705 removed\_email\_address@domain.invalid  
KOREA

---

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [August 31, 2007, 3:55pm UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/4 "2007-08-31T15:55:51Z")

</div>

Saji,

Interesting, that would make sense. You could also do  
floods.parts.find\_or\_initialize\_by\_name(“body”) if you don’t want to  
drop the parts.

Sean

---

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [December 19, 2007, 5:00pm UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/5 "2007-12-19T17:00:56Z")

</div>

I’m resurrecting an old thread just before starting to look at it  
myself. I’m likely to work on a project where it will be needed to  
update a large number of pages. I think it may be possible to dump the  
content out to a bunch of files from where it should be possible to pick  
up the pages, add the usual stuff and update the pages to a Radiant site  
using a script.

Is there anyone doing so using the script below or something similar?  
Would it be possible to share?

I’ve never used script/runner with a live site but I’m willing to look  
at the relevant stuff in the Rails world to make that happen. But I’m  
just starting to wonder how to keep this site scalable (since it  
involves the migration of about 7 books from PDF to Radiant) with a  
bunch of relatively standard things to be included on each page.

Thanks,  
Mohit.  
12/19/2007 | 11:58 PM.

---

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [December 19, 2007, 5:31pm UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/6 "2007-12-19T17:31:24Z")

</div>

Thanks Saji,

It serves as a great example to see-and-learn!!

Cheers  
Mohit.

---

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [December 19, 2007, 5:28pm UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/7 "2007-12-19T17:28:27Z")

</div>

Hi Mohit,

We control our own server, and it is easy to do stuff like this.  
Here is a script that I use to update or add certain parts of our  
website (currently offline).

Hope it is helpful.

saji

# ---------- %\< start of code

#!/usr/bin/ruby  
require File.dirname( **FILE** ) + ‘/…/config/boot’  
require ‘commands/runner’

class String  
attr\_accessor :slug  
end

if ARGV.length==0  
puts “USAGE : updateWeb YYYY MON service”  
puts “for example : updateWeb 2007 NOV monitoring”  
exit  
end  
months =%w( JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC)

def updateContents(pPage,cPage,cSlug,filter,parts,contents)  
puts “Updating contents of #{pPage}/#{cPage}”  
myPage = Page.find\_by\_url(pPage+“/”+cSlug)  
myPage.parts.clear  
nparts=parts.size  
0.upto(nparts-1) do |i|  
myPage.parts.create(  
:content =\> contents[i],  
:name =\> parts[i],  
:filter\_id =\> filter)  
end  
myPage.update  
puts “Finished Updating”  
end

def createPage(pPage,cPage,cSlug)  
puts “Adding Page #{pPage}/#{cPage}”  
parent=Page.find\_by\_url(pPage)  
child = parent.children.create(  
:title =\> cPage.capitalize,  
:breadcrumb =\> cPage,  
:slug =\> cSlug,  
:status\_id =\> “100”)  
child.save!  
end

def checkForPage(pPage,cPage,cSlug)  
child= Page.find\_by\_url(pPage+“/”+cSlug)  
neClass=child.class  
if neClass==FileNotFoundPage  
createPage(pPage,cPage,cSlug)  
end  
end

year=ARGV[0]  
month=ARGV[1]  
service=ARGV[2]  
product=ARGV[2]

# check and create reports page

case service  
when “Monitoring”  
service=service+“/Highlights/”  
when “Prediction”  
service=service+“/Outlook/”  
when “ISV”  
service=“Monitoring/Analysis/”+service+“/CurrentStatus/”  
when “Drought”  
service=“Monitoring/Analysis/”+service+“/CurrentStatus/”  
end

# For each part of the services string delimited by “/”

# check for existence, if not create the page

servicePages = service.split(“/”)  
pPage=“/services”  
servicePages.each do |service|  
servLow=service.downcase  
cPage=service  
cSlug=servLow  
checkForPage(pPage,cPage,cSlug)  
pPage=pPage+“/”+servLow  
end

# check and create reports/YYYY page

cPage=year  
cSlug=cPage  
checkForPage(pPage,cPage,cSlug)  
body=\<\<END\_OF\_BODY  
\<r:children:first\>  
\<r:content /\>  
\</r:children:first\>  
END\_OF\_BODY

sidebar=\<\<END\_OF\_SIDEBAR

### Archives By Month

\<r:find url=“#{pPage}”\>  
\<r:content part=“sidebar” /\>  
\</r:find\>  
END\_OF\_SIDEBAR

parts=[“body”,“sidebar”]  
contents=[body,sidebar]  
filter=“”  
updateContents(pPage,cPage,cSlug,filter,parts,contents)

# check and create reports/YYYY/MON page

pPage=pPage+“/”+cSlug  
cPage=month  
cSlug=(months.index(month) + 1).to\_s  
checkForPage(pPage,cPage,cSlug)

# check this directory and upload text files and image files separately

product=“/Reports/#{product}/#{year}/#{month}”  
prodDir=File.dirname( **FILE** )+“/…/public/#{product}”  
allFiles=`ls #{prodDir}`.split

txtFiles=[]  
allFiles.each { |a| txtFiles.push([a]) unless File.extname(a)==“.png”}  
exit if txtFiles.size==0  
exit if txtFiles.size\>1  
imgFiles=[]  
allFiles.each { |a| imgFiles.push([a]) if File.extname(a)==“.png”}  
exit if imgFiles.size==0

txtFile=txtFiles.first.join  
content=File.read(prodDir+“/”+txtFile)  
txt=\<\<END\_OF\_TXT  
\<r:content part=“image” /\>  
END\_OF\_TXT  
content=content + “\n”+ txt  
img\_describe=“ ![]()”

parts=[“body”,“image”]  
contents=[content,img\_describe]  
filter=“Maruku”  
updateContents(pPage,cPage,cSlug,filter,parts,contents)

# ------- %\< end of code

- Mohit S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) [2007-12-19 23:59:41 +0800]:

> I’ve never used script/runner with a live site but I’m willing to look
> 
> > flood news")  
> > parent.children \<\< child  
> > Saji Njarackalazhikam H. wrote:
> > 
> > > :breadcrumb =\> “Floods”, :slug =\> “floods”)
> > > 
> > > # ---- test script that does not work
> > > 
> > > Radiant mailing list  
> > > Search: [http://radiantcms.org/mailing-list/search/](http://radiantcms.org/mailing-list/search/)  
> > > Site: [http://lists.radiantcms.org/mailman/listinfo/radiant](http://lists.radiantcms.org/mailman/listinfo/radiant)  
> > > –  
> > > Saji N. Hameed

APEC Climate Center +82 51 668 7470  
National Pension Corporation Busan Building 12F  
Yeonsan 2-dong, Yeonje-gu, BUSAN 611705 removed\_email\_address@domain.invalid  
KOREA

---

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [December 19, 2007, 5:34pm UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/8 "2007-12-19T17:34:54Z")

</div>

Saji N Hameed wrote:

> Hi Mohit,
> 
> We control our own server, and it is easy to do stuff like this.  
> Here is a script that I use to update or add certain parts of our  
> website (currently offline).
> 
> Hope it is helpful.
> 
> saji

Looking at this answers the fundamental question I had!! I was  
concerned about how the authentication is handled to get past the  
admin. But, of course, when we use script/runner, we’re usually  
accessing the models directly rather than through the controllers - and  
the controllers are where the before\_filters for authentication will  
usually be!

That said, I guess this means that it’s best for the script to be local  
to the site - so, I can’t get it to submit from my desktop to the server  
machine. The script should ideally be on the server where the site is  
running.

Is this how you’re using it, Saji?

Cheers,  
Mohit.  
12/20/2007 | 12:33 AM.

---

<div class="post-metadata">

**Author:** ![saji](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/c6cbf5/32.png) [@saji](https://www.ruby-forum.com/u/saji)\
**Post date:** [December 19, 2007, 6:03pm UTC](https://www.ruby-forum.com/t/updating-a-page-using-script-runner/113162/9 "2007-12-19T18:03:04Z")

</div>

- Mohit S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) [2007-12-20 00:33:42 +0800]:

> > 
> 
> machine. The script should ideally be on the server where the site is  
> running.
> 
> Is this how you’re using it, Saji?

Well, the web-server is a different machine, but we have  
full access to it. We run a drb server on the  
web-server and installed clients on other machines. Users upload  
stuff from their desktops to the webserver through this mechanism.

I remember Sean’s advise that you may be able to use Capistrano  
for this purpose. That may be worth checking out.

Anyway, I am attaching scripts for the client and servers  
we use.

best wishes,  
saji

# — this is the drb server that sits at the web-server

#!/usr/bin/env ruby

require ‘drb’  
require ‘drb/acl’

@baseDir=ENV[‘RadiantHOME’]+“/customScripts”

# this order is important, so do not move the

# the require statement below

require File.join(File.dirname( **FILE** ), ‘server\_methods’)

puts “Will Exit if not executed in right Directory”  
exit unless `pwd`.chomp == @baseDir

if **FILE** == $0  
acl = ACL.new(%w( deny all allow 190.1.1.121 allow 220.84.94.58 allow  
localhost ) )  
DRb.install\_acl(acl)  
DRb.start\_service(“druby://:7777”, OurClass.new)  
puts “Drb server running at #{DRb.uri}”  
trap(“INT”) {DRb.stop\_service }  
DRb.thread.join  
end

# — some methods used by the DRb object

require ‘net/ftp’

class OurClass

def chDir(wDir,year,month)  
wDir=“/home/saji/MyTestServer/public/Reports/”+wDir+“/”+year+“/”+month  
`mkdir -p #{wDir}`  
@wDir=wDir  
end

def ftpFiles(ftpsite,login,password,wDir,txt,img)  
“Opening new ftp session for #{ftpsite}”  
ftp=Net::FTP.new(ftpsite)  
ftp.login(user=login,passwd=password)  
ftp.chdir(wDir)  
“Retrieving Image files”  
ftp.getbinaryfile(img,@wDir+“/”+img)  
“Retrieving Text files”  
ftp.gettextfile(txt,@wDir+“/”+txt)  
ftp.close  
“ftp over”  
end

def updateWeb(service,year,month)  
# run an update  
retVal=[]  
ENV[‘RAILS\_ENV’]=“production”  
ls = IO.popen(“…/script/runner updateWeb #{year} #{month}  
#{service}”,“r”)  
while line = ls.gets  
retVal \<\< line  
puts line  
end  
ls.close  
return(retVal)  
end

end

# — The ncurses based client that is used to upload information to the

# web-page via DRb server

#!/usr/bin/env ruby  
require “rdialog”  
require ‘drb’

@months=%w(JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC)  
dialog = RDialog.new  
dialog.nocancel = true  
@thisMonth=@months[Time.today.mon - 1]  
@thisYear=Time.today.year.to\_s

def updateWebPage  
meSg = @webServer.updateWeb(@product,@year,@month)  
dialog = RDialog.new  
dialog.nocancel = true  
dialog.shadow = false  
tst=dialog.infobox(meSg, height=0, width=0)  
end

def interactWithRemoteServer  
@webServer = DRbObject.new nil, ‘druby://190.1.1.24:7777’  
@webServer.chDir(@product,@year,@month)  
wDir=@wDir+“/”+@year+“/”+@month  
meSg=@webServer.ftpFiles(@ftpsite,@login,@password,wDir,@txt,@img)  
dialog = RDialog.new  
dialog.nocancel = true  
dialog.shadow = false  
tst=dialog.msgbox(meSg, height=0, width=0)  
updateWebPage  
end

def findLoginDetails  
dialog = RDialog.new  
dialog.nocancel = true  
dialog.shadow = false  
@ftpsite = dialog.inputbox(text=“IP address of your machine”,  
height=20,width=60, init=“190.1.1.121”)  
defLogin=`whoami`.chomp  
@login = dialog.inputbox(text=“Your login”, height=0,width=0,  
init=defLogin)  
@password = dialog.passwordbox(text=“Enter your password”,  
height=0,width=0,init=“”)  
end

def checkFiles  
dialog = RDialog.new  
dialog.nocancel = true  
dialog.shadow = false  
allFiles=`ls`.split  
txtFiles=[]  
allFiles.each { |a| txtFiles.push([a]) unless File.extname(a)==“.png”}  
exit if txtFiles.size==0  
myText = dialog.radiolist(text=“Chose Text Files”, items=txtFiles)  
imgFiles=[]  
allFiles.each { |a| imgFiles.push([a]) if File.extname(a)==“.png”}  
exit if imgFiles.size==0  
myImgs = dialog.checklist(text=“Chose Image Files”, items=imgFiles)  
@txt = myText  
@img = myImgs[0]

findLoginDetails  
interactWithRemoteServer  
end

def prepareForTransport  
dialog1 = RDialog.new  
dialog1.nocancel = true  
dialog1.shadow = false  
Dir.chdir(@wDir)  
myDate = dialog1.calendar(text=“Select a Date”, height=0, width=0,  
day=-1, month=Date.today.mon(), year=Date.today.year())  
myMonth = myDate.mon()  
myYear = myDate.year  
@month = @months[myMonth - 1]  
@year = myYear.to\_s  
Dir.chdir(@year)  
Dir.chdir(@month)  
checkFiles  
end

prod\_type = Array.new  
prod\_type.push([“Monitoring Highlights”])  
prod\_type.push([“Prediction Outlook”])  
prod\_type.push([“ISV Highlights”])  
prod\_type.push([“Drought Highlights”])

services = dialog.checklist(“Chose a Service”,prod\_type)

for service in services  
prefix = service.split[0]  
workDir=ENV[“CIS\_#{prefix.upcase}”]  
exit if workDir==nil  
exit unless File.exist?(workDir)  
@wDir=workDir  
@product=prefix  
prepareForTransport  
end

> * * *
> 
> Radiant mailing list  
> Post: removed\_email\_address@domain.invalid  
> Search: [http://radiantcms.org/mailing-list/search/](http://radiantcms.org/mailing-list/search/)  
> Site: [http://lists.radiantcms.org/mailman/listinfo/radiant](http://lists.radiantcms.org/mailman/listinfo/radiant)

–  
Saji N. Hameed

APEC Climate Center +82 51 668 7470  
National Pension Corporation Busan Building 12F  
Yeonsan 2-dong, Yeonje-gu, BUSAN 611705 removed\_email\_address@domain.invalid  
KOREA
