DataMapper save fails but with no errors - ruby

When I try to modify and then save a model using DataMapper I get a SaveFailure exception but no errors.
Specifically I see this message:
"MonthlyBill#save returned false, MonthlyBill was not saved"
This is the code doing the saving:
post '/monthly_bills' do
with_authenticated_user do |user|
description = params[:description]
expected_amount = params[:expected_amount]
pay_period = params[:pay_period]
monthly_bill = MonthlyBill.new(:description=>description, :expected_amount=>expected_amount, :pay_period=>pay_period)
user.monthly_bills << monthly_bill
user.save
end
The User model:
class User
include DataMapper::Resource
property :id, Serial
property :email_address, String
property :password, String
has n, :monthly_bills
has 1, :current_pay_period
end
The MonthlyBill model:
class MonthlyBill
include DataMapper::Resource
property :id, Serial
property :description, String
property :expected_amount,Decimal
property :pay_period, Integer
belongs_to :user
end
What is the issue and, more importantly, how can I get DataMapper to tell me more specifically what is wrong?

Hmm - those capitalised properties look worrying to me. I would do...
has n, :monthly_bills
has 1, :current_pay_period #do you really have a CurrentPayPeriod model?!
And then try:
monthly_bill = MonthlyBill.new(:description=>description,:expected_amount=>expected_amount, :pay_period=>pay_period, :user=>user)
monthly_bill.save

Related

NoMethodError: Undefined method `first_or_create' for "foo":String

I have used this method before in a Sinatra application with Datamapper without any troubles.
Now it doesn't seem to work. Any ideas appreciated.
My test:
scenario 'add hashtags to posts' do
visit '/'
add_post('Stacca',
'Hello! out there',
%w(foo bar))
post = Post.first
expect(post.hashtag.map(&:text)).to include('foo')
expect(post.hashtag.map(&:text)).to include('bar')
end
My server
post '/posting' do
username = params['username']
message = params['message']
hashtag = params['hashtag'].split(' ').map do |hashtag|
hashtag.first_or_create(text: hashtag)
end
Post.create(username: username, message: message, hashtag: hashtag)
redirect to ('/')
end
My Models:
class Post
include DataMapper::Resource
property :id, Serial
property :username, String
property :message, String
has n, :hashtag, through: Resource
end
and:
class Hashtag
include DataMapper::Resource
has n, :posts, through: Resource
property :id, Serial
property :text, String
end
Thank you
This line:
hashtag.first_or_create(text: hashtag)
should be:
Hashtag.first_or_create(text: hashtag) # uppercase!
Else, you are just trying to call a non existing "first_or_create" method on the String ("foo") you got from the scenario. 'Hashtag' is your class, 'hashtag' is your (String) variable.
Hashtag.first_or_create(text: hashtag)
Hashtag should have been a class
i.e. you missed the capital

Ruby Datamapper: retrieving record using param in url path returns null - sometimes

I'm creating a Sinatra App using Datamapper.
With the following route, I'm attempting to print the record for an id. So localhost:9292/api/1 should return results for id=1
inside
get '/api/:id' do
I tried a couple things with varied results:
thing = Thing.get(params[:id])
thing.to_json
end
outputs 'null', but:
id_param = params[:id]
id_param
end
prints 1 as expected, and:
hardcoded_thing = Thing.get(1)
hardcoded_thing.to_json
end
correctly prints the hardcoded db record with id=1. So I must be losing it..
Any ideas?
Thanks!
For reference, here's my model:
class Thing
include DataMapper::Resource
include BCrypt
property :id, Serial, :key => true
property :created_at, DateTime
property :updated_at, DateTime
property :name, String, :length => 50
property :cafe_topic, Text
end
Try this:
get '/api/:id' do |id|
thing = Thing.get(id)
thing.to_json
end

Create JSON from 2 associated Datamapper models

Here is my question.
I have 2 associated Datamapper models:
class Task
include DataMapper::Resource
property :id, Serial
property :date, Date
property :amount, Float
belongs_to :project, :required => true
end
class Project
include DataMapper::Resource
property :id, Serial
property :name, String, :required => true
property :desc, Text
belongs_to :company
has n, :tasks
end
My goal is to created JSON that will contain task date, amount and project name, that should be matched by project_id. At the moment JSON generation has following look:
Task.all.to_json(:only => [:date, :amount, :project_id])
I can access project_id from Task model, but have no idea how to add respective project name from Project model for every task. In SQL it looks like join:
select tasks.date, tasks.amount, projects.name from tasks
inner join projects
on tasks.project_id = projects.id;
Can you suggest correct way to create final JSON, using Datamapper way, but not SQL?
Thank you.
I have found solution for my problem. Here it is:
# create new structure to store merged result
Task_entry = Struct.new(:date, :amount, :pname)
# array to get results from database
all_task_items = Array.new
# run through result and fill the array with required data
Task.all.each do |task|
task_item = Task_entry.new(task.date, task.amount, task.project.name)
all_task_items << task_item
end
all_task_items.to_json # generate json
It works for me well. Hope it can be helpful.

Correct way to make a DataMapper association

I want to have a table of users. These users shall have n contacts and n messages..
My code is:
...
class User
include DataMapper::Resource
property :id, Serial, :key => true
property :nickname, String
has n, :contacts
has n, :messages
end
class Contact
include DataMapper::Resource
belongs_to :user
property :id, Serial, :key => true
property :authgiven, String
has 1, :user
end
class Message
include DataMapper::Resource
belongs_to :user
property :id, Serial, :key => true
property :data, String
end
#apply models (validation etc.)
DataMapper.finalize
...
There are no errors initializing DataMapper, but when I try to create a new User or whatever, save always returns false... Can someone please point out what is wrong?
I'm quite new to DataMapper, it always worked for me with simple tables without relationships, so I believe it has to do with the way I declared the 1:n relationship...
Hey you should remove that has 1, :user line from Contact model and you should be good.

Error happens when I read items in DataMapper

class List
include DataMapper::Resource
property :id, Serial
property :name, String
property :items, String
end
List.auto_migrate!
get '/:id' do
#list = List.all(:id => params[:id])
#items = #list.items
erb :show
end
I get undefined method `items' for #. Any ideas?
You fetch a collection of lists instead of a single list instance, that's why you get the error. I believe you want to do:
#list = List.get(params[:id])

Resources