How to use ActiveRecord callbacks to assign field values before save? - activerecord

I'm wondering how I can use callbacks to assign values to the database fields, which are processed out of a virtual attribute field.Example:
field :houseno, :type => String
field :street, :type => String
attr_accessor :address
My attempt at this seems to be unsuccessful. Here is what I have:
before_validation :assign_fields
def assign_fields
if #address
#houseno = #address.match(/^(\d+-?(\d+)?)\W*(.*)/)[1]
#street = #address.match(/^(\d+-?(\d+)?)\W*(.*)/)[3]
end
end
And I keep getting this error:
undefined method `houseno' for Building:0x0000010488f108

Have you tried:
write_attribute(:houseno) = #address.match(/^(\d+-?(\d+)?)\W*(.*)/)[1]
or
self.houseno = #address.match(/^(\d+-?(\d+)?)\W*(.*)/)[1]

Related

Cheezy's Page Object, get all text_fields defined inside Page

considering this simple Page Object:
require 'watir-webdriver'
require 'page-object'
class SomePage
include PageObject
text_field :first_name, :name => "fname"
text_field :last_name, :name => "lname"
text_field :birth_date, :name => "birthday"
button :submit, :type => "submit"
end
browser = Watir::Browser.new
page = SomePage.new(browser)
is there a way to iterate over all the text fields (or any elements) to access their "identifier" (i.e. :username, :password or :birth)?
something like:
page.text_fields.each do |text_field|
puts text_field.identifier.inspect
end
=> :first_name
=> :last_name
=> :birth_date
I'm just looking to see if I could turn this:
page.first_name = #user.first_name
page.last_name = #user.last_name
etc...
into this:
page.text_fields.each do |text_field|
attribute = text_field.attribute
text_field = #user[attribute]
end
Anybody knows what I mean?
The answers already provided definitely will suite your needs, but I would like to add one additional option that uses a feature built into the page-object gem.
It's call populate_page_with() in page_populator.rb. It's used like this so.
Start with a hash that has the element names(I use a CSV file that is loaded into a hash), as defined on your page object, in the keys. The value of the hash contains the value you wish to populate each element with.
form_data = {first_name: #user.first_name, last_name: #user.last_name, birth_date: #user.birth_date}
#page.populate_page_with form_data
That's it. The populate_page method will find the right elements on the page and populate them with whatever value you have set in your source hash. This works for checkbox, radio buttons and text.
This is a very nice time saving method that Cheezy put in for us!
Thanks Cheezy!
The names (:first_name, :last_name, :birth_date) are only used to generate the method names such as first_name=, last_name= and birth_date=. The name is not stored or retained for later use.
That said, you could iterate through the page's instance methods to find the text fields. The following text_fields method will:
Get all of the class instance methods.
Find the methods that end with "_element".
Create an array that includes the element names and element.
The page object would be:
class SomePage
include PageObject
text_field :first_name, :name => "fname"
text_field :last_name, :name => "lname"
text_field :birth_date, :name => "birthday"
button :submit, :type => "submit"
def text_fields
self.class.instance_methods(false)
.grep(/_element$/)
.map { |m|
element = self.send(m)
[m[/(.+)_element$/, 1].to_sym, element] if element.kind_of?(PageObject::Elements::TextField)
}.compact
end
end
You could then iterate through the text fields with access to their name (or attribute) and the TextField element:
page = SomePage.new(browser)
page.text_fields.each do |attribute, text_field|
text_field.value = #user[attribute]
end
I do exactly the "opposite" :
#user.each do | key, value |
unless value.empty?
browser.text_field(label: key).set value
end
end
I make the job done for the datas I have, and not the fields. It allows to test form fill with only some fields.

How to search the associated model values using 'dusen' gem

In rails 4.0.2, I am trying to use a search plugin called dusen. Using this, I can search same model's values but I am not able to search other(associated) model values. How can I achieve this for single association(has_one / belongs_to) & multi association(has_many) model values?
Reference link:
https://github.com/makandra/dusen
Gem which I am using is dusen (0.4.10)
In controller,
#query = params[:query] || ""
Contact.search(#query)
In model,
belongs_to :city, :class_name=>"City"
search_syntax do
search_by :text do |scope, phrases|
columns = [:name, :contact_number, :email]
scope.where_like(columns => phrases)
end
end
Here, It will search only :name, :contact_number, :email fields, if i try to add below piece of code then it will show an error like undefined method 'search_text' for #<Dusen::Description:0xb438a248>
search_text do
[city.name]
end
Please suggest a solution for this issue.
Assuming your model name is 'User', you'd set it up as follows:
# User.rb
belongs_to :city, :class_name=>"City"
search_syntax do
search_by :text do |scope, phrases|
# namespaced fields to search by.
columns = ["users.name", "users.contact_number", "users.email", "cities.name"]
# specify association to City in scope.
scope.joins(:city).where_like(columns => phrases)
end
end
I hope this helps!

Mongomapper embedded document "Cannot serialize an object" error

I'm quite new to mongodb and I'm using sinatra and mongomapper to update the values of an embedded document with the following set up:
class TeamMember
include MongoMapper::Document
key :name, String, :required => true
many :team_member_projects
end
class TeamMemberProject
include MongoMapper::EmbeddedDocument
key :date, Date, :required => true
one :project
end
class Project
include MongoMapper::Document
key :name, String, :required => true
end
The modifier code is:
team_member = TeamMember.find(params[:team_member])
project = Project.find(params[:project])
date = Date.parse(params[:date])
tm_project = TeamMemberProject.new(:project => project, :date => date)
team_member.push(:team_member_projects => tm_project)
team_member.save
but I get the error for .push line:
BSON::InvalidDocument at /project/add
Cannot serialize an object of class TeamMemberProject into BSON.
Did I not declare my embedded document properly? Or is there another way to update embedded documents, I don't know about. I'm trying to use: http://mongomapper.com/documentation/plugins/modifiers.html#push
This seems to work
team_member = TeamMember.find(params[:team_member])
project = Project.find(params[:project])
date = Date.parse(params[:date])
tm_project = TeamMemberProject.new(:project_id => project.id, :date => date)
team_member.team_member_projects << tm_project
team_member.save
It seems like I have to use project.id. Not sure why. Also not sure why my .push doesn't work, as I would have assumed it does the same thing as <<.

How to save received string parameters in array field?

How to extract and save array from string parameter? I'm trying convert string beafore_create but this doesn't work. When I comment before_create :waypoints Mongoid throw error:
Parameters: {
"utf8"=>"✓",
"authenticity_token"=>"nehoT1fnza/ZW4XB4v27uZsfFjjOu/ucIhzMmMKgWPo=",
"trip"=>{
"title"=>"test",
"description"=>"test",
"waypoints"=>"[[52.40637,16.92517],[52.40601,16.925040000000003],[52.405750000000005,16.92493],[52.40514,16.92463],[52.404320000000006,16.924200000000003]]"
}
}
Completed 500 Internal Server Error in 1ms
Mongoid::Errors::InvalidType (Field was defined as a(n) Array, but received a String with the value "[[52.40637,16.92517],[52.40601,16.925040000000003],[52.405750000000005,16.92493],[52.40514,16.92463],[52.404320000000006,16.924200000000003]]".):
EDIT Thanks for help, now it work but I don't know whether following approach is good. I remove before_create and change parameter name from waypoints to waypoints_s and def waypoints to def waypoints_s:
#Parameters:
#"waypoints"=>"[[52.40637,16.92517],[52.40601,16.925040000000003],[52.405750000000005,16.92493],[52.40514,16.92463],[52.404320000000006,16.924200000000003]]"
"waypoints_s"=>"[[52.40637,16.92517],[52.40601,16.925040000000003],[52.405750000000005,16.92493],[52.40514,16.92463],[52.404320000000006,16.924200000000003]]"
class Trip
include Mongoid::Document
field :title, :type => String
field :description, :type => String
field :waypoints, :type => Array
#before_create :waypoints
#def waypoints=(arg)
def waypoints_s=(arg)
if (arg.is_a? Array)
##waypoints = arg
self.waypoints = arg
elsif (arg.is_a? String)
##waypoints = arg.split(',')
self.waypoints = JSON.parse(arg)
else
return false
end
end
end
class TripsController < ApplicationController
def create
#trip = Trip.create(params[:trip])
#trip.save
end
end
Parse the string as a JSON object:
require 'json'
waypoints = "[[52.40637,16.92517],[52.40601,16.925040000000003],[52.405750000000005,16.92493],[52.40514,16.92463],[52.404320000000006,16.924200000000003]]"
JSON.parse(waypoints)
=> [[52.40637, 16.92517], [52.40601, 16.925040000000003], [52.405750000000005, 16.92493], [52.40514, 16.92463], [52.404320000000006, 16.924200000000003]]
You need to use serialize http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-c-serialize
This method serialize your object to database by YAML format (let's say just text with some format).
class Trip < ActiveRecord::Base
serialize :waypoints
end
trip = Trip.create( :waypoints => [[52.40637,16.92517],[52.40601,16.925040000000003],[52.405750000000005,16.92493],[52.40514,16.92463],[52.404320000000006,16.924200000000003]])
Trip.find(trip.id).waypoints # => [[52.40637,16.92517],[52.40601,16.925040000000003],[52.405750000000005,16.92493],[52.40514,16.92463],[52.404320000000006,16.924200000000003]]

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