Datamapper update enum value through form - ruby

I have a model like this:
class Project
include DataMapper::Resource
property :id, Serial
property :title, String
property :slug, String
property :status, Enum[:open, :closed ], :default => :open
has n, :issues
end
I've created a view to update the project status:
<form action="/project/update" method="post" id="project">
<label for="status">Status
<select id="status">
<option value="0"
<% if(#project.status == :open) %>
selected="selected"
<% end %>
>Open</option>
<option value="1"
<% if(#project.status == :closed) %>
selected="selected"
<% end %>
>Closed</option>
</select>
</label>
</form>
Here's the route:
post '/project/update' do
#project = Project.get(params[:project_id])
#project.update(:title => params[:title])
end
What values does the form need to pass to the route to update the status? and what should the route look like in this instance?
Thanks,

"open" and "closed" - they will be converted to symbols automatically.

Related

Add usernames to database

I have this line in an .erb file to get the input of the username
<input type="text" placeholder="User Name" name="user[username]" value="<%#{#user.username}%>" class="form-control">
for my User.rb class I have the following:
class User
include DataMapper::Resource
property :id, Serial
property :username, String
property :password, String
property :role, String
end
DataMapper.finalize()
get '/users' do
#users = User.all
erb :users
Within users.erb I have the following
<div class="container">
<h3>Users</h3>
<% if #users.any? %>
<ul <%#users%>>
<% #users.each do |user|%>
<li><%#{user.username}%></li>
<%end%>
<%else%>
<p>No Users in database</p>
<%end%>
</ul>
</div>
I want the to login a user and have that username stored in the database and then display that on the users page but it just keeps getting the else statement and I don't know why

Ruby each loop based on array

I have an array like this:
#airports = [
['Malaysia', 'Alor Setar', 'AOR'],
['Malaysia', 'Bintulu', 'BTU'],
['Malaysia', 'Ipoh', 'IPH'],
['Malaysia', 'Johor Bahru', 'JHB'],
['Indonesia', 'Kuching', 'KCH'],
['Indonesia', 'Labuan', 'LBU'],
['Indonesia', 'Langkawi', 'LGK'],
['Indonesia', 'Miri', 'MYY'],
['Indonesia', 'Penang', 'PEN'],
]
then in my view:
<select name="from" class="form-control select2">
<% #airports.each do |airport| %>
<optgroup label="<%= airport[0] %>">
<option value="<%= airport[2] %>" <%= #params[:from] == airport[2] ? "selected" : "" %>>
<%= "#{airport[1]} (#{airport[2]})" %>
</option>
</optgroup>
<% end %>
</select>
which gives the result like this:
How can I group it for each country? I mean like this:
Malaysia
Alor Setar
Bintulu
Ipoh
Johor
Indonesia
Kuching
Labuan
Langkawi
Penang
Miri
In your view, you can do something like:
<% countries = #airports.group_by{|a| a.first} %>
<% countries.each do |country, airport| %>
<optgroup label="<%= country %>">
<% airport.each do |a| %>
<option value="<%= a[1] %>"></option>
<% end %>
</optgroup>
<% end %>
PS: This is just to give you a rough idea, I'm missing the logic you used for <option value> in my example. Hope you can fix it accordingly.

Sinatra to-do list tutorial problems

So, I'm new to Ruby/Sinatra, did a bunch of codecademy lessons and the like. I decided until I actually built something, I wouldn't really understand some core concepts.
I found a tutorial for building a to-do list app in Sinatra, and all was fine and good until I got to the edit and delete functionality. I can read and write to/from the database, but whenever I try to edit or delete, it skips straight to "Note not found".
I couldn't figure this out myself, so I asked a developer friend of mine. When I sent him the code, everything worked absolutely fine for him! We tried a couple of different possible fixes, but to no end. I even downloaded the code from the guy's github, just in case there was a random mistake somewhere in my own code, to no avail.
So, I come here asking for some help! Why won't this work!
Clarification: Here's some of the code, where I think the problem may lie. In edit.erb and delete.erb, no matter what it is going to the else statement and sending me to "note not found". It's reading properly from the database, as my homepage can add and show notes.
recall.rb
get '/:id' do
#note = Note.get params[:id]
#title = "Edit note ##{params[:id]}"
erb :edit
end
put '/:id' do
n = Note.get params[:id]
n.content = params[:content]
n.complete = params[:complete] ? 1 : 0
n.updated_at = Time.now
n.save
redirect '/'
end
get '/:id/delete' do
#note = Note.get params[:id]
#title = "Confirm deletion of note ##{params[:id]}"
erb :delete
end
delete '/:id' do
n = Note.get params[:id]
n.destroy!
redirect '/'
end
edit.erb
<% if #note %>
<form action="/<%= #note.id %>" method="post" id="edit">
<input type="hidden" name="_method" value="put">
<textarea name="content"><%= #note.content %></textarea>
<input type="checkbox" name="complete" <%= "checked" if #note.complete %>>
<input type="submit">
</form>
<p>Delete</p>
<% else %>
<p>Note not found.</p>
<% end %>
delete.erb
<% if #note %>
<p>Are you sure you want to delete the following note: <em>"<%= #note.content %>"</em>?</p>
<form action="/<%= #note.id %>" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="Yes, Delete It!">
Cancel
</form>
<% else %>
<p>Note not found.</p>
<% end %>
Moving the delete-route above the other routes seemed to work for me, which would suggest that the /:id -part in the route definition catches the /delete-part as well. You can see the generated regexps with Sinatra::Application.routes.
Here's a minimal:
require 'rubygems'
require 'sinatra'
require 'dm-core'
require 'dm-migrations'
require 'dm-sweatshop'
# Models
DataMapper.setup(:default, 'sqlite::memory:')
class Note
include DataMapper::Resource
property :id, Serial
property :content, Text, :required => true
property :complete, Boolean, :default => false
property :created_at, DateTime, :default => lambda {Time.now}
property :updated_at, DateTime
before(:save) { attribute_set(:updated_at, Time.now) }
end
DataMapper.finalize.auto_migrate!
# Fixtures
Note.fix {{
:content => /\w+/.gen
}}
100.of { Note.gen }
# Routes
before("/:id") {|id| #note = Note.get id }
get("/:id/delete") {|id| #note = Note.get id; erb :delete }
get("/:id") { erb :edit }
put "/:id" do
#note.attributes = params["note"]
#note.save ? redirect(to("/")) : erb(:edit)
end
delete("/:id") { #note.destroy; redirect(to("/")) }
# Templates
template :layout do
'<!DOCTYPE html>
<html>
<body><%= yield %></body>
</html>'
end
template :edit do
'<% if #note %>
<form action="/<%= #note.id %>" method="POST">
<input type="hidden" name="_method" value="PUT">
<textarea name="note[content]"><%= #note.content %></textarea>
<input type="checkbox" name="note[complete]"
<%= #note.complete? && "checked" %> >
<input type="submit">
</form>
<p>Delete</p>
<% else %>
<p>Note not found.</p>
<% end %>'
end
template :delete do
'<% if #note %>
<p>Are you sure you want to delete the following note:
<em>"<%= #note.content %>"</em>?</p>
<form action="/<%= #note.id %>" method="POST">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="Yes, Delete it!">
Cancel
</form>
<% else %>
<p>Note not found</p>
<% end %>'
end
I don't know if this is still interesting someone, but a simple
params[:id].to_i
fixed it for me.

Sinatra/Carrierwave: how to update a record while using an existing image?

My super-simple Sinatra app is a list of notes, and each note has an attached image.
I've got a 'put' route set up that lets me update notes, but unless I re-upload the image, I lose it (note.image is set to 'nil' when I submit the form).
Thanks in advance for your help!
Here's my uploader:
class MyUploader < CarrierWave::Uploader::Base
include CarrierWave::MimeTypes
process :set_content_type
storage :fog
end
Here's my Note class:
class Note
include DataMapper::Resource
property :id, Serial
property :image, String, :auto_validation => false
property :content, Text, :required => true
property :created_at, Date
property :updated_at, Date
mount_uploader :image, MyUploader
end
Here's my 'put' route:
put '/:id' do
n = Note.get params[:id]
unless n
redirect '/', :error => "Can't find that note."
end
n.image = params[:image]
n.credit = params[:content]
n.date = params[:date]
n.updated_at = Time.now
if n.save
redirect '/', :notice => 'Note updated successfully.'
else
redirect '/', :error => 'Error updating note.'
end
end
And here's the form I'm using to update notes:
<% if #note %>
<form action="/<%= #note.id %>" method="post" id="edit" enctype="multipart/form-data">
<input type="hidden" name="_method" value="put">
<p><input type="text" name="credit" value="<%=h #note.content %>"></p>
<p><input type="file" name="image" /></p>
<br><br>
<input type="submit">
</form>
<% else %>
<p>Note not found.</p>
<% end %>
A simple if check is what you need: if params[image] is nil you skip the n.image = params[:image]
n.image = params[:image] if params[:image]
I use similar approach to create a custom Rails validation check when I work with ActiveRecord models that contain CarrierWave images. Probably it won't be a bad idea to check whether or not n.image isn't nil as well - if it's nil I guess it should be mandatory to upload an image.

Sinatra and Datamapper - inserting data to a one to many relationship table

I have the following. Each article has a title and a body and also up to three urls. I would want to store the urls in a different table. Therefore in my form, i've a field for the urls. However they are not working, only the article fields get entered into the database. how should i specify them? Could any kind soul help me out with this?
class Article
include DataMapper::Resource
property :id, Serial
property :title, String
property :body, Text
has n, :urls, through => Resource
end
class Url
include DataMapper::Resource
property :id, Serial
property :url_01, String
property :url_02, String
property :url_03, String
belongs_to :article
end
post '/create' do
#article = Article.new(params[:article])
if #article.save
redirect "/articles"
else
redirect "/articles/new"
end
end
--------------------------------------
<form action="/create" method="post">
<p>
<label>Article Title</label>
<input type="text" name="article[title]">
</p>
<p>
<label>Article Body</label>
<input type="text" name="article[body]">
</p>
<p>
<label>Url</label>
<input type="text" name="article[url_01]">
</p>
<p>
<input type="submit">
</p>
I believe that
, through => Resource
is only needed if you are doing a many-to-many relationship. A one-to-many, which I think is what you want, does not require that. Check out the post and comment relationship shown on the associations page.
EDIT for comment:
If I were you, I would name my form fields normally and construct the database object manually, for example:
<form action="/create" method="post">
<p>
<label>Article Title</label>
<input type="text" name="title">
</p>
<p>
<label>Article Body</label>
<input type="text" name="body">
</p>
<p>
<label>Url</label>
<input type="text" name="url">
</p>
<p>
<input type="submit">
</p>
and then:
post '/create' do
#article = Article.new(
:title => params[:title],
:body => params[:body]
)
#url = url.new(
url_01 => params[:url]
)
#article.url = #url
if #article.save
redirect "/articles"
else
redirect "/articles/new"
end
end

Resources