In Datamapper, getting "NoMethodError - undefined method `get!' for nil:NilClass:" - ruby

I have two tables, mapped out for datamapper:
class User
include DataMapper::Resource
property :id, Serial, :field => 'ID'
property :user_first_name, String, :field => "USER_FIRST_NAME"
property :user_last_name, String, :field => "USER_LAST_NAME"
has n, :login_sessions, :child_key => [ :user_id ], :parent_key => [ :id ]
end
and
class LoginSession
include DataMapper::Resource
property :id, Serial, :field => 'ID'
property :user_id, Integer, :field => "USER_ID"
property :login_time, DateTime, :field => "LOGIN_TIME"
belongs_to :user, :parent_key => [ :user_id ], :child_key => [ :id ]
end
Given a LoginSession object, I want to get the corresponding user:
session = LoginSession.first(:id => 1)
if session
# code reaches here, meaning that session is not nil.
user = session.user
end
When I run this code, at user = session.user, I get the following error:
NoMethodError - undefined method `get!' for nil:NilClass:
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm- core/property_set.rb:88:in `block in get!'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/support/subject_set.rb:210:in `block in each'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `block in each'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `each'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/support/ordered_set.rb:319:in `each'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/support/subject_set.rb:210:in `each'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/property_set.rb:88:in `map'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/property_set.rb:88:in `get!'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:289:in `source_key_different?'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/associations/many_to_one.rb:179:in `lazy_load'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:23:in `lazy_load'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/resource/persistence_state/persisted.rb:8:in `get'
/Users/Tom/.rvm/gems/ruby-1.9.3-p362/gems/dm-core-1.2.0/lib/dm-core/model/relationship.rb:340:in `user'
/Users/Tom/Projects/api_server/app.rb:197:in `block in <class:MyApp>'
...
I can't figure out what I'm doing wrong. I'm assuming that the LoginSession object can't find a corresponding user method or something? Please help!

Related

Watir: Passing dynamic selector

Is there a way to pass a dynamic set of options to a textarea element in browser?
options = {
:type => 'textarea',
:selector => ':id',
:field => 'id_of_textarea_field',
:value => 'Joe Salesperson'
}
browser.textarea(options[:selector] => options[:field]).set ''
Error received:
invalid attribute: ":id"
A similar thread is listed here (selecting elements using variables in ruby /watir) but no answer.
options = {
:type => 'textarea',
:selector => :id,
:field => 'id_of_textarea_field',
:value => 'Joe Salesperson'
}
You can just pass the identifier, no need for quotes.
2017-01-03, Updating with a use case. Here is the declaration of the method I'm using and the call. The actual code is much more verbose and contains different validations than what I've pasted here. In the example, you'll notice a simple switch block which sets the appropriate information based on the element type passed (specifically text areas, text fields, and select elements).
def validateInput(options = {})
success = true
begin
case options[:type]
when 'textarea', 'text_field'
Watir::Wait.until{$browser.textarea(options[:selector] => options[:field]).present?}
$browser.textarea(options[:selector] => options[:field]).set options[:value]
when 'select'
$browser.select_list(options[:selector] => options[:field]).select_value options[:value]
else
puts "in else"
end
end
rescue => e
$message.push("Failed to validate '#{options[:field]}' field. #{e}")
success = false
end
return success
end
validateInput({
:type => 'textarea',
:selector => :id,
:field => 'order_approval_comment_name',
:value => 'Joe Salesperson'
})

Chef: Undefined node attribute or method `<<' on `node' when trying to add

In my attributes file for postgresql recipe I have:
default['postgresql']['pg_hba'] = {
:comment => '# IPv4 local connections',
:type => 'host',
:db => 'all',
:user => 'all',
:addr => '127.0.0.1/32',
:method => 'md5'
}
I want to my recipe automatically add my servers to pg_hga config file like this:
lambda {
if Chef::Config[:solo]
return (Array.new.push node)
end
search(:node, "recipes:my_server AND chef_environment:#{node.chef_environment} ")
}.call.each do |server_node|
node['postgresql']['pg_hba'] << {
:comment => "# Enabling for #{server_node['ipaddress']}",
:type => 'host',
:db => 'all',
:user => 'all',
:addr => "#{server_node['ipaddress']}/32",
:method => 'trust'
}
end
include_recipe 'postgresql'
But I'm receiving an error:
NoMethodError
-------------
Undefined node attribute or method `<<' on `node'
35: node['postgresql']['pg_hba'] << {
36: :comment => "# Enabling for #{server_node['ipaddress']}",
37: :type => 'host',
38: :db => 'all',
39: :user => 'all',
40: :addr => "#{server_node['ipaddress']}/32",
41: :method => 'trust'
42>> }
43: end
44:
45: include_recipe 'postgresql'
Your problem is here:
node['postgresql']['pg_hba'] << {
This way you're accessing the attribute for reading.
Assuming you want to stay at default level you have to use default method like this:
node.default['postgresql']['pg_hba'] << { ... }
This will call default method (like in attribute file) to add the entry.
For this to work the first attribute declaration should be an array (or a hash of hash) like this:
default['postgresql']['pg_hba'] = [{ # notice the [ opening an array
:comment => '# IPv4 local connections',
:type => 'host',
:db => 'all',
:user => 'all',
:addr => '127.0.0.1/32',
:method => 'md5'
}] # Same here to close the array

Creating a class and adding methods dynamically in Ruby

How do I go about creating a new class and adding a few methods to it without resorting to "eval"?
Here's what I'm trying to do; I'd like to transform this structure:
obj = [
{
:scope => 'account',
:fields => [
{ :title => 'title', :length => 64, :required => true },
{ :title => 'email', :length => 256, :required => true, :type => 'email' }
],
:before_save => Proc.new{
#do something here
},
},
{
:scope => 'product',
:fields => [
{ :title => 'title', :length => 64, :required => true },
{ :title => 'description', :length => 256, :required => true },
{ :title => 'cost', :required => true, :type => 'decimal' }
]
},
]
into this:
class Account
include DataMapper::Resource
property :id, Serial
property :title, String, :length => 64, :required => true
property :email, String, :length => 256, :required => true
def before_save
#do something here
end
end
...
Thanks!
As Andrew already said, there are different ways to create class dynamically. This could be one of them:
Say you start with one DM model (haven't used DM, taking the first one from the docs):
class Post
include DataMapper::Resource
property :id, Serial # An auto-increment integer key
property :title, String # A varchar type string, for short strings
property :body, Text # A text block, for longer string data.
property :created_at, DateTime # A DateTime, for any date you might like.
end
and you want to create it dynamically, from a metadata given in a hash of the form
{:ClassName => {:field1 => :Type1, :field2 => :Type2 ...}}
You could do:
require 'data_mapper'
models = {:Post => {
:id => :Serial,
:title => :String,
:body => :Text
}}
models.each do |name, fields|
klass = Class.new do
include DataMapper::Resource
fields.each do |field_name, field_type|
property(field_name, const_get(field_type))
end
end
Object.const_set(name, klass)
end
Key methods:
Class.new
Module#const_set
If you want to look at a real-world example, please consult the code in this library: https://github.com/apohllo/rod/blob/v0.7.x/lib/rod/model.rb#L410

How to check if hash cookie value is set?

Normally I have:
cookies[:location] = { :value => { :city => 'foo', :country => 'bar' } }
However, sometimes :country is not set. When I do:
cookies[:location][:country].present?
to check if country has been set, it returns an error:
[:country] is not a symbol
How would I check to see if a country is set in cookie[:location] if I cannot do it this way?
You cookies hash is nested differently than you are expecting: :value is nested under :location, :city and :country are nested under :value. Here is some irb output to get you started:
[~]$ irb
>> cookies={}
=> {}
>> cookies[:location] = { :value => { :city => 'foo', :country => 'bar' } }
=> {:value=>{:city=>"foo", :country=>"bar"}}
>> cookies[:location][:value][:country]
=> "bar"
>> cookies.to_s
=> "{:location=>{:value=>{:city=>\"foo\", :country=>\"bar\"}}}"
If you nest the hash like below, you will get your expected behavior:
>> cookies[:location] = { :city => 'foo', :country => 'bar' }
=> {:city=>"foo", :country=>"bar"}
>> cookies[:location][:country]
=> "bar"

Cannot modify data with Mongoid

I can read my database using Mongoid, but cannot write to it.
This example below successfully outputs the activity's device type, but it crashes on the save method with this error message: "undefined method `name' for nil:NilClass"
activity = Activity.find('4d89568d4f21557eb10003fc')
puts activity.deviceType
activity.description = 'my description'
activity.save
Here are my class definitions:
class User
include Mongoid::Document
field :name, :type => String
field :identifier, :type => String
field :email, :type => String
referenced_in :activity
end
class Trackpoint
include Mongoid::Document
field :when, :type => DateTime
field :latitude, :type => Float
field :longitude, :type => Float
field :distance, :type => Float
field :altitude, :type => Float
field :heartRate, :type => Integer
embedded_in :activity, :inverse_of => :trackpoint
end
class Activity
include Mongoid::Document
field :startTime, :type => DateTime
field :description, :type => String
field :sport, :type => String
field :deviceType, :type => String
field :deviceId, :type => String
field :deviceActivityId, :type => String
field :isPublic, :type => Boolean
field :user_id, :type => String
embeds_many :trackpoints
references_one :user
end
Thanks for any help...
Just got rid of the :inverse_of statements and it works now!

Resources