I got this sample code from datamapper http://datamapper.org/getting-started.html
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
Can anyone tell me that how "property" generate? Is it a function, variable, class variable or instance variable or a constant?
sometime i also saw this kind of code
class CarModel
attribute :name
attribute :hello
end
but no idea how does this generate
It is a method that is included when you do:
include DataMapper::Resource
You can see its source code here if you're interested in digging in deeper.
It basically adds a property to the list of properties in your Post resource.
Related
I am just learning Ruby and datamapper, I have read the docs about associations from the official DataMapper site, but I still have two problems.
First whenever I add associated object, I can not see it when displaying all objects.
I have test class like:
class Test
include DataMapper::Resource
property :id, Serial
property :name, String
has 1, :phonen, :through => Resource
end
And then phonen class like:
class Phonen
include DataMapper::Resource
property :id, Serial
property :number, String
belongs_to :test
end
Then I am creating those 2 objects
#test = Test.create(
:name => "Name here"
)
#phone = Phonen.create(
:number => "Phone number"
)
#test.phonen = #phone
#test.save
And I want to display them like that (I want to return json)
get '/' do
Test.all.to_json
end
What am I doing wrong? maybe its something with the to_json...
I honestly don't know..
But I have one additional question to this topic, lets say I managed to connect those two classes, if I display JSON will I get Phonen { } or just inside class { }?
I know its probably very easy question, but I can't figure it out. That's why I decided to ask you guys. Thanks for help
Test.all
Is returning an active record association in array form, not a hash, when you try to convert to json it's failing.
You can try:
render json: Test.all
As asked in this question:
Ruby array to JSON and Rails JSON rendering
This is a get started example of Ruby data mapper. However, how does this example illustrate the power of datamapper that separate the application logic and data persistence?
Any better example can give us that the separation can lead us do unit test more easily?
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
# create makes the resource immediately
#post = Post.create(
:title => "My first DataMapper post",
:body => "A lot of text ...",
:created_at => Time.now
)
# Or new gives you it back unsaved, for more operations
#post = Post.new(:title => ..., ...)
#post.save # persist the resource
Thanks!
I'm just starting in on DataMapper and find myself doing this sort of thing a lot:
class MyModel
include DataMapper::Resource
property :id, Serial
property :serialized_credentials, String
def credentials
#credentials ||= YAML.load(self.serialized_credentials)
end
def credentials=(c)
#credentials = nil
self.serialized_credentials = YAML.dump(c)
end
end
This allows me to pass a hash (for example) for credentials.
But does DataMapper already provide a mechanism for this?
You can use the Object type DataMapper provides:
class MyModel
include DataMapper::Resource
property :id, Serial
property :credentials, Object
end
This will however use Marshal.dump instead of YAML.dump, but you could DRY this up by defining your own type:
class YAMLObject < DataMapper::Type
primitive String
def self.dump(value, property)
Base64.encode64(YAML.dump(value))
end
def self.load(value, property)
value.nil? ? nil : YAML.load(Base64.decode64(value))
end
end
Then you can use it just like any other type:
class MyModel
include DataMapper::Resource
property :id, Serial
property :credentials, YAMLObject
end
Last but not least there is the Json type available from the dm-types gem which uses MultiJson to dump and load the data.
References (Object Type):
http://datamapper.rubyforge.org/dm-core/DataMapper/Types/Object.html
http://datamapper.org/docs/properties.html
References (Define own Type):
http://datamapper.rubyforge.org/dm-core/DataMapper/Type.html
References (Json Type):
https://github.com/datamapper/dm-types
It looks like there are native DataMapper types you can use too.
From http://datamapper.org/docs/dm_more/types.html:
Serializers
These store values in the data-store using text based serialization
formats. They work via calling dumping the object to the format on
saving and parsing the text to reinitialize them on loading.
Csv
Json
Yaml
So something like
class MyModel
include DataMapper::Resource
property :id, Serial
property :credentials, Json
end
class Order
include Datamapper::Resource
property :birthday_day, String
property :birthday_month, String
property :birthday_year, String
property :birthday, Date
before :save do
#birthday = Date.new(#birthday_year.to_i, #birthday_month.to_i, #birthday_day.to_i)
end
end
It's a part of model, but it's enouth.
When save field (from irb or from sinatra application) :birthday not save in DB. But in irb, i see object, where :birthday exist and it Date format.
When change field manual (from irb):
f.birthday = Date.new
f.save
In object and in DB result appear (in obj as Date obj, in DB as "2010-2-3")
Help me please to understand, what wrong with before in model.
Sorry for my not good enlish.
You should use property mutator method. Setting the ivar doesn't trigger dirty tracking. Just do this:
self.birthday = Date.new(birthday_year.to_i, birthday_month.to_i, birthday_day.to_i)
Also it would be better to use Integer as the property type for year, month and day.
DataMapper documentation recommends #attribute_set
Sets the value of the attribute and marks the attribute as dirty if it has been changed so that it may be saved. Do not set from instance variables directly, but use this method.
In your case:
before :save do
set_attribute(:birthday => Date.new(self.birthday_year.to_i, self.birthday_month.to_i, self.birthday_day.to_i))
end
For what it's worth, unless I needed to use all the fields in SELECT criteria, I would save either the integer fields or the date, not both:
class Order
include Datamapper::Resource
property :birthday, Date
end
# change month
o = Order.create(:birthday => Date.new(...))
o.update(:birthday => Date.new(o.birthday.year, new_month, o.birthday.mday))
Or
class Order
include Datamapper::Resource
property :birthday_day, String
property :birthday_month, String
property :birthday_year, String
def birthday
if self.birthday_day && self.birthday_month && self.birthday_year
Date.new(self.birthday_day, ...)
end
end
end
I`m trying to figure out how to get serial and key attributes set for Resource object. Basic method DataMapper::Resource.attributes returns a collection of properties, but it does not say anything about types. Of course i can check it via system call: obj.class, but cant understand how to get type information from resource instance.
Example:
class Foo
include DataMapper::Resource
property :id, Serial
property :title, String, :required => true
property :created_at, Time, :required => true
property :flagged, Boolean, :default => false
end
So, is there any way to get this information about internal types for resource?
Not long time ago, i figured it out by myself. All model fields are basically instances of DataMapper::Property
So, all you need is to call ModelName.properties and get options like :index, :key, etc.
Description: http://yardoc.org/docs/datamapper-dm-core/DataMapper/Property