12.07.08

Got Backup?

On thursday morning, my hard drive died at the age of (almost) 4. I’m really glad I’m backing up my data every hour. So the whole process of getting everything up and running again was really inconvenient, but was no catastrophe!

For 58€ my disc space is now doubled (160GB now) and I had the opportunity to have a look inside my Powerbook. ;-)

Got Backup?

So: don’t be careless and backup regularly!

11.07.08

Status

It’s been a long time since I last updated the blog. I have been really busy creating the in-house application (here at innoq) for invoice management and time reporting. And as this is my diploma thesis, too, I’m now occupied with writing the thesis.

“innoVoice”: that’s the title of the application (or at least the working title).
The app is now up and running for approx. 50 days and is in production mode concerning the management of invoices. The time reporting part is being tested by co-workers this month.

As you may have followed my design mockups of the time reporting screen, I thought I’d share the (for now) final design:

Note to self: I should update this blog more regularly!

29.04.08

Lesson learned

A part of my ER-Model is not correct:

The many-to-many association between Projects and Users is simply wrong. Imagine a simple case of an deletion of a relation between an User and a Project - for example the user/employee stopped working on that particular project - causes the project also to disappear from Timereports in the past.
And this is fundamentally wrong, because he surely did work on that project!

And so the connection should be between Projects and Timereports!!! Like this:

I’m pretty sure this has to be modelled this way.
Now if the user stops working on a particular project, it’s no problem to do that deletion.

Project has_many :timereports, :through => :projects_timereports
######
Timereport has_many :projects, :through => :projects_timereports
######
ProjectsTimereports has_many :timereportentries

Ok, now I’ll have to re-code that and I hope it won’t me drive nuts to do this, because I really could have avoided it!

23.04.08

ActiveResource and Associations

Ok, it’s been quite a while since the last post popped up here; that’s because I struggled with the innoQ internal timereporting- and invoicing-application I’m working on, which is my diploma thesis, too.
And here’s one of my problems I had…

Preface

Concerning users that are going to use my application, there has been a change made, so my app is no longer responsible for user management. This is now all done by a separate application. And this applications has a REST interface which I have access to and should obtain my user data from, as well as handle authentication. I now look at the “obtain data” part, because the authentication part is definitely worth another blog post.

ActiveResource basics

Now: receiving data from another Rails app with a REST interface is quite simple. In the model (in my case User) you inherit from ActiveResource::Base instead of ActiveRecord::Base and specify a site url to the remote Rails application. Like this:

class User < ActiveResource::Base
    self.site = "http://the.url.to/yourapp/"
end

Now you can obtain user data almost the same way you do with ActiveRecord classes:

User.find(2) # finds the user with the id of '2'

or even

User.find(:all) # finds all users in the remote app

if you like.

My problem

But what if your resource is somehow associated with your local model and database?
In my case an user has many projects and a project has many users. So here you have a many-to-many relationship.

That really is more difficult for problems like “I’d like to obtain all users for a specific project” and vice versa, because you can’t just make up a many-to-many relationship as you would with two ActiveRecord objects. Like this:

has_and_belongs_to_many :projects # or
has_many :projects, :through => 'projects_users'

In a class which inherits from ActiveResource this is not supported/allowed.
Ok, in my project model these statements would work, because it is an ActiveRecord object. But all the methods you gain through this won’t work either, because they don’t know the you are referencing a model of type ActiveResource and all finds will fail.

So what to do?
Here’s what works for me (so far).
But I’m sure there are many more ways out there to solve this, and I’d really appriciate every comment on this topic, ‘cause I am curious if there’s a more elegant solution. So, there you go:

My solution

Remember the initial situation:

Project (ActiveRecord - in my app) (M)—————-(has)—————(N) User (ActiveResource - remote app)

So first of all I created a join table and the corresponding join model by typing (in the console, of course):

script/generate model projects_users

This creates a model for me with along with a migration file. Inside this file I write these lines:

class CreateProjectsUsers < ActiveRecord::Migration
  def self.up
    create_table :projects_users do |t|
      t.integer :project_id, :user_id, :null => false
      t.string :color, :null => false
    end
  end

  def self.down
    drop_table :projects_users
  end
end

An advantage of join models is that you can store additional attributes in the join table. The only thing I store along the project_id and the user_id is a color. That’s just relevant for the front-end to display the project in the correct color, so don’t get irritated. ;-)

Then, I ran the migration:

rake db:migrate

Now, let’s head over to the association part.
As you can’t put any associations in a ActiveResource model, there’s nothing to do in the User model.

In the Project model I put a has_many statement:

has_many :projects_users, :class_name => "ProjectsUsers"

(Note, that in my case I had to explicitly tell the class_name of the join model class, because Rails assumes this to be singular, i.e. ProjectUser.)

In the ProjectsUsers model I wrote the following two lines:

belongs_to :project
belongs_to :user # so far this isn't used by me, but it may be useful some day

Now the interesting part: How can you get all users for a given project in a way like project.users.find(:all)?
In project.rb, define a method called users:

def users
    user_ids = self.projects_users.find(:all, :select => "user_id")
    users = user_ids.collect { |projects_users| User.find(projects_users.user_id) }
end

Now via project.users you’ll get all the users you need.
(I’m pretty sure you can rewrite this, so that it works the railsway and you can call project.users.find(:all) instead, but I haven’t tried it, yet)

Ok, the other way round, meaning obtaining all projects for a specific user, I faked it a bit, and I’m sure you can do better here, too. But it works!
Instead of creating a projects method in the User model, I coded a method called self.find_by_user_id in the Projects model:

def self.find_by_user_id(userid)
    project_ids = ProjectsUsers.find_all_by_user_id(userid, :select => "project_id")
    projects = project_ids.collect { |projects_users| projects_users.project }
end

You can call it this way:

user_projects = Project.find_by_user_id(2)

And BOOM!, you have all projects for the user no. 2.

That’s all folks! This was my solution/workaround for integrating a REST-Resource via a many-to-many association in Rails. Hope you liked it. :-)

05.04.08

Rails and in_place_editor issues

Ok, so the last few days I had a bit of a struggle concerning the script.aculo.us in place editor and the corresponding plugin/helper in rails.
So here are my links that really helped me solving these issues:

If you have more interesting links regarding the in_place_editor and rails, feel free to leave a comment right here. Thanks.

27.03.08

Euruko this weekend! [UPDATE]

This weekend the Euruko conference takes place in Prague. It's all about Ruby and I'll gonna be there.
I'm quite excited, as this is my first (big) conference I'm going to attend. I think most of the talks will be pretty advanced for a Ruby beginner like me, but I think I won't get dumber... ;-)

Unfortunately we'll probably miss Matz' Keynote, because our flight arrives at 09:30 in the morning and to think we'll be in the center of Prague at 10 o'clock would be really optimistic...

[UPDATE] We managed to get to prague university almost in time, so we saw most of the keynote:

Venue

I'm also looking forward to visiting Prague again, 'cause it really is a beautiful city - and affordable, too. That's why I'll stay until late tuesday. :-)

11.03.08

More ER-Modelling

Once more, I improved the model of my application. I wasn’t satisfied with the fact, that I was indeed able to store the time report data for each day of the month, but have an UI on a monthly basis and so one screen for multiple DailyReports.
Now I modelled it the way, that I have a (monthly) TimeReport which has many DailyReports. This way a DailyReport belongs to a Project and a (monthly) TimeReport. And a TimeReport belongs to a specific user/employee.

That’s exactly how I wanted it to be from the beginning. I don’t no why this took me this long…

Now it’s also no problem to get nice URLs for a TimeReport. For example like this: http://…/TimeReport/DanielPietzsch/2008/3/ for March 2008.

28.02.08

Third (and probably last) time reporting mockup

Besides thinking about how to model my database I continued working on the UI:

Ok, maybe you don’t see that much difference since the last mockup, but I refined most of the div-structure beneath the surface and did some minor design changes.
But the biggest improvement is, that the calendar is now based on real dates. I must admit that the calendar helper plugin helped me with the code.

The bullet-points on the 28th are a representation for all calendar fields, where you entered any hours. If you didn’t enter an other number than 0 the day cell stays empty (for display). If you want the add or modify hours on a particular day, you click the cell and via an in-place editor you can enter your information. (That’s the plan).

I’m not quite sure if the coloring of the weekends will stay that way…I think I’ll decide later, since this is not the most important decision to make.

Now I think I should concentrate on the real app, meaning all the functionality and model behind the UI.

26.02.08

Altered ER-Model [UPDATE]

I altered a part of my ER-Model concerning the implementation of the time-reporting:

There’s no longer an entity called “Arbeitszeit” (working time). All the worked hours and days should now get stored in the extra many-to-many-table that’ll be created in between “Stundenzettel” (timesheet) and “Projekt” (project). That table might have the following attributes: StundenzettelID, ProjektID, workingTimeTotal, dailyTimes, notes.
So far I’m not sure how to store all the hours to their corresponding days in dailyTimes (because that’s at least about 30 values every month and user), but I might use a plain text field which contains a somehow-delimited list of working-hours (ascending from the 1st to the last day of the month).

The “Mitarbeiter” (co-worker) entity is also the applications entity for storing login- and user-information.

What you see on the latest mockup, is in Rails the update- or new-action/view for the “Stundenzettel”-controller. I think there won’t be any implementation of a read- or delete-action for “Stundenzettel” (timesheets).

So, I hope this will work for me…

And yes, next time the ER-Model will be in english, too, that I don’t have to bother you (and me) with this language mix. I also code in english, so this makes sense anyway.

[UPDATE]

After talking to Tim and Phillip and considering Stefans Comment, I think this is the right way of modelling the Entity Relationship:

So, in the DailyReport entity there is the attribute Date which is an additional primary key to the ProjectID and the UserID. This way the WorkedHours are stored for every day. So you have a table for every day, employee and project.
The same with notes. This may be useful to describe your tasks on that day, for example. This way I think I’ll have to reengineer the UI, ‘cause notes do not get stored on a monthly basis. I already have something in mind for that.

[/UPDATE]

22.02.08

Second UI mockup

The second mockup of the applications UI. I thought I stick to the design of innoq.com, so co-workers are somehow familiar with the layout. The (div-)structure underneath is quite different than the one of innoq.com, but I copied some design-elements so far.

Take a look:

In the top-right corner you now have the ability to add one or more projects you’re currently working on. They’ll be differentiated by colors. In the calendar you’ll find the corresponding fields for these projects. Again: I think I’ll hide most of these field in normal view, using an in-place editor.

I’m still really curious what your opinion is…

About

DanielHi. I'm Daniel Pietzsch and this is my innoQ-Blog. I'm a 26y old student at FH Bochum and working student at innoQ.
In this blog I mainly write about the progress concerning my diploma thesis which will be an in-house application for innoQ based on Ruby on Rails, but some other (geek) stuff might appear here, too.

daniel [dot] pietzsch [alt-L] innoq [dot] com

I recommend

Categories

Recent Comments

License

Creative Commons License This weblog is licensed under a Creative Commons License.
Powered by
Movable Type 3.31