📜 ⬆️ ⬇️

We write REST application on Sinatra and we fasten Redactor. Part 1

This article is designed first for newbies who are just starting to learn Ruby. After 3 weeks of learning this wonderful language, some knowledge has accumulated that I want to share.

Sinatra is a free and open source software framework written in the Ruby language for developing web applications. ( ru.wikipedia.org )

Redactor is quite powerful and at the same time simple and beautiful to use wysiwyg editor ( link to Habré )

So, let's begin!
Presumably you already have Ruby and SQLite installed.
Since the main point of the article is an attempt to fasten Redactor, where thumbnails are already used for previewing images, previews of images are used, then we install Rmagick to work with images. In OS X, installation is fairly simple.
curl https://raw.github.com/maddox/magick-installer/master/magick-installer.sh | sh 

Now you need to install additional gems.
 [sudo] gem install sinatra data_mapper carrierwave carrierwave/datamapper json shotgun 

sintra - the framework itself
data_mapper - ORM
carrierwave - heme for loading images (used in one article on Habré)
carrierwave / datamapper - for communication DataMapper and CarrierWave
json - to generate data in JSON format
')
The necessary gems are installed, now download the editor itself redactorjs.com/en/download

Let's start writing the code:
Classics of the genre
 # coding: utf-8 require 'sinatra' get '/' do 'REST   Sinatra <a href="/posts">  </a>' end 

let's save for example as init.rb and run the application shotgun init.rb
go to the address http://127.0.0.1:9393/


You have noticed the link / posts, now we will deal with its performance.
The first thing we need to do is add the gems we set to the application.
 #init.rb # coding: utf-8 require 'rubygems' require 'sinatra' require 'data_mapper' require 'carrierwave' require 'carrierwave/datamapper' require 'rmagick' require 'json' 

Set the public folder with js scripts and where we will upload images (also usually css files, page layout images are placed in this folder)
 set :public_directory, './public' 

And immediately create a js folder in it and copy the previously downloaded editor there.

Next, we write our model Post
 #init.rb class Post include DataMapper::Resource property :id, Serial # property :title, String #String   ,   title    ""     50  property :body, Text #Text   ,   body    ""  65535  end 

Create a folder db in the root with our file init.rb
Set up a database
 #init.rb DataMapper.setup(:default, ENV['DATABASE_URL'] || 'sqlite:./db/base.db') #     DataMapper.finalize #  DataMapper.auto_upgrade! #          

Prescribe routing for / posts
 #init.rb #   get '/posts' do #   /posts @posts = Post.all #  @posts        Post erb :'index' #    index.erb* end 

* by default Sinatra uses erb template engine - Erubis

Now we will create the views folder in the root with our init.rb file, again, by default, Sinatra is looking for templates in the views folder. Create in this folder index.erb as follows:
 #index.erb <strong><a href="/posts/new">  </a></strong> <h2>  </h2> <% @posts.each do |post| %> <strong><a href="/posts/<%= post.id %>/edit"><%= post.title %></a></strong><br> <%= post.body %><br> <% end %> 

Let's look at some points:
Remember, we in the get '/ posts' do request set the @posts = Post.all variable ? So, by the construction of <% @ posts.each do | post | %> ....... <% end%> we are looking for in the array all posts available in the database.
/ posts / <% = post.id%> / edit - link to edit the post, we will access the posts through their id
<% = post.title%> - we print in the template the name of the post
<% = post.body%> - output in the template body of the post

Now we need to create a common template for all pages, where we will connect all custom css and js. Create a layout.erb file in the views folder and run a little ahead and create a posts folder in the same directory and there are 2 edit.erb and new.erb files in it. Now the structure of the application should be like this:

 #layout.erb <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Redactor.js + Sinatra app</title> </head> <body> <%= yield %> </body> </html> 

<% = yield%> - instead, various templates that we created will be displayed - index.erb, new.erb, edit.erb

Now we need to make the link / posts / new
Add to init.rb
 #init.rb #Create new Post get '/posts/new' do #     erb :'posts/new' #  /posts/new.erb end post '/posts/new' do params.delete 'submit' @post = Post.create(params) # ,        Post redirect '/posts' #      end 

And we add in views / posts / new.erb
 #new.erb <h3></h3> <form method="post" action="/posts/new"> <label for="title"><strong>:</strong></label><br> <input id="title" type="text" name="title" value="" style="width: 250px;"> <br> <label for="body"><strong> :</strong></label><br> <textarea id="body" name="body" style="height: 250px;"></textarea> <br> <input type="submit" name="submit" value=""> </form> 

Follow the link "Create a new page"

Add data, click the button "Create", the post is created.

Now add some code to edit and delete pages.
 #init.rb #Edit post get '/posts/:id/edit' do #   ,       id @post = Post.get(params[:id]) #  @post      id  erb :'posts/edit' #  /posts/edit.erb end #Update post put '/posts/:id/edit' do post = Post.get(params[:id]) post.title = (params[:title]) post.body = (params[:body]) post.save #   redirect '/posts' #      end #Delete post get '/posts/:id/delete' do Post.get(params[:id]).destroy #  redirect '/posts' end 

Edit views / posts / edit.erb
 #edit.erb <h3></h3> <a href="/posts/<%= @post.id %>/delete"> </a><br><br> <form action="/posts/<%= @post.id %>/edit" method="post"> <input name="_method" type="hidden" value="put" /> <label for="title"><strong>:</strong></label><br> <input type="text" name="title" id="title" value="<%= @post.title %>"> <br> <label for="body"><strong> :</strong></label><br> <textarea id="body" name="body" style="height: 250px;"><%= @post.body %></textarea> <br> <input id="post_submit" name="commit" type="submit" value=""> </form> 

In fact, the application is ready to use, now about the second part of the article, this is to attach Redactor to textarea

First, connect it. Open views / layout.erb, add after
 #layout.erb <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript" src="/js/redactor/redactor.js"></script> <link rel="stylesheet" href="/js/redactor/css/redactor.css" type="text/css"> 

Now we will configure (in more detail about setup it is possible to read here ).
 #layout.erb <script type="text/javascript"> $(document).ready(function() { $('.redactor_1').redactor({toolbar: 'default', lang: 'ru', imageUpload: '/upload/image', imageGetJson: '/uploads/images/imageslist.json'}); }); </script> 

$ ('. redactor_1') - call the editor with the name redactor_1
toolbar: 'default' - set up a standard toolbar with all buttons
lang: 'ru' - set the Russian language
imageUpload: '/ upload / image' - so we will upload images
imageGetJson: '/uploads/images/imageslist.json' - so we will get previews and a list of already downloaded images

Now let's call the editor for textarea, to do this, open views / posts / new.erb and views / posts / edit.erb and add the class class = "redactor_1". For example, new.erb should now look like this:
 #new.erb <h3></h3> <form method="post" action="/posts/new"> <label for="title"><strong>:</strong></label><br> <input id="title" type="text" name="title" value="" style="width: 250px;"> <br> <label for="body"><strong> :</strong></label><br> <textarea id="body" class="redactor_1" name="body" style="height: 250px;"></textarea> <br> <input type="submit" name="submit" value=""> </form> 

And edit.erb like this:
 #edit.erb <h3></h3> <a href="/posts/<%= @post.id %>/delete"> </a><br><br> <form action="/posts/<%= @post.id %>/edit" method="post"> <input name="_method" type="hidden" value="put" /> <label for="title"><strong>:</strong></label><br> <input type="text" name="title" id="title" value="<%= @post.title %>"> <br> <label for="body"><strong> :</strong></label><br> <textarea id="body" class="redactor_1" name="body" style="height: 250px;"><%= @post.body %></textarea> <br> <input id="post_submit" name="commit" type="submit" value=""> </form> 

Let's create in the public folder the uploads folder in it the images folder. The directory structure is public / uploads / images.
Now we realize the loading of images through gem CarrierWave. Configure in init.rb:
 #init.rb class ImageUploader < CarrierWave::Uploader::Base def store_dir 'uploads/images' #     end def extension_white_list %w(jpg jpeg gif png bmp) #   jpg, jpeg, gif, png, bmp end include CarrierWave::RMagick # RMagick    version :thumb do process :resize_to_fill => [100,74] # RMagick'       end storage :file end 

As Redactor shows us already uploaded images through their previews, which in turn reads from a JSON file, which we call imageslist.json and lies in public / uploads / images /. We need to bring this same file to a format that Redactor understands.
 { "thumb": "/tests/_images/1_m.jpg", "image": "/tests/_images/1.jpg" }, 

Hence it follows that we need to create a model as follows.
 #init.rb class UploadedImages #      include DataMapper::Resource property :id, Serial property :image, String # property :thumb, String # mount_uploader :file, ImageUploader #  carrierwave end 

At the very end of the init.rb file we add the following:
 #init.rb post '/upload/image' do params[:file] filename = params[:file][:filename] file = params[:file][:tempfile] upload = UploadedImages.new upload.file = params[:file] upload.image = params[:image] = '/uploads/images/' + File.join(filename) #      upload.thumb = params[:thumb] = '/uploads/images/thumb_' + File.join(filename) #       upload.save # -  @images = UploadedImages.all #   @images          JSON File.open("public/uploads/images/imageslist.json","w") do |f| # imageslist.json   f.write JSON.pretty_generate(@images) # JSON       end '<img src="/uploads/images/' + File.join(filename) + '" />'#    textarea    end 


What's happening? When you upload an image, the contents of imageslist.json are deleted and a new one is generated. Honestly, I do not know how much it is expensive for the server.

If the article finds its response, the next time I will try to describe the process of downloading files through this editor, as well as the interface for managing downloaded images.

Source code can be viewed on github .

PS: I beg you not to scold me much, I tried to put everything on the shelves. Of course, I understand that my code is far from ideal, and some points can be implemented more simply, but I think this is a good starting point for starting learning Ruby and Sinatra. Thank.

PSS: Everywhere Where You Go
 <hh user=posts> 
or
 <hh user=images> 
just replace with @posts and images, respectively.

Source: https://habr.com/ru/post/144277/


All Articles