Beginner Error in Rails: confusing an attribute of ActiveRecord instanze with an instance variable

Angelegt von suung Wed, 19 Oct 2011 11:56:00 GMT

As Ruby programmer you are used to write code like this, if you want to have a default value or rather make sure, that something is an Array or Hash, in order to rely on that for later treatment

 

  def filters

    @filters ||= { }

  end

In Active Record that does not work, cuz:

@query.instance_variable_get :@filters
=> nil
and
 
@query.attributes

=> {"name"=>"_", "column_names"=>nil, "group_by"=>nil, "project_id"=>1, "sort_criteria"=>nil, "user_id"=>0, "search_mode"=>"all", "filters"=>{:subproject_id=>{:value=>[], :operator=>"*"}}, "is_public"=>false}



there is also obie's great post about this: http://www.jroller.com/obie/entry/default_values_for_activerecord_attributes

pry - alternative to irb and making debugging any ruby application (including rails) fun

Angelegt von andi Mon, 05 Sep 2011 23:21:00 GMT

Definitely check out this railscasts: http://railscasts.com/episodes/280-pry-with-rails

  • walk into ruby objects ( cd Array; self # => Array; cd new; self #=> [] )
pry(main)> cd Array
pry(Array):1> self
=> Array
pry(Array):1> cd new
pry([]):2> self
=> []
  • ls -m shows the current objects methods
pry(main)> cd Array
pry(Array):1> ls -m
[:[], :allocate, :new, :superclass, :try_convert, :yaml_tag]

  • reload-method reloads the file containing the method specified, edit-methods open up your code editor with the file containing the method (cursor at the correct method) thus, when you use pry for debugging, you can play with a method, edit it, reload it, play with it again.

  • help lists all available commands :)

Command List: 
--
help              This menu.
install-command   Install a disabled command.
toggle-color      Toggle syntax highlighting.
simple-prompt     Toggle the simple prompt.
pry-version       Show Pry version.
import-set        Import a command set
reload-method     Reload the source file that contains the specified method
reset             Reset the REPL to a clean state.
ri                View ri documentation. e.g `ri Array#each`
show-doc          Show the comments above METH. Type `show-doc --help` for more info. Aliases: ?
stat              View method information and set _file_ and _dir_ locals. Type `stat --help` for more info.
gist-method       Gist a method to github. Type `gist-method --help` for more info.
gem-install       Install a gem and refresh the gem cache.
gem-cd            Change working directory to specified gem's directory.
gem-list          List/search installed gems. (Optional parameter: a regexp to limit the search)
ls                Show the list of vars and methods in the current scope. Type `ls --help` for more info.
cd                Start a Pry session on VAR (use `cd ..` to go back and `cd /` to return to Pry top-level)
nesting           Show nesting information.
jump-to           Jump to a Pry session further up the stack, exiting all sessions below.
exit              End the current Pry session. Accepts optional return value. Aliases: quit, back
exit-all          End all nested Pry sessions. Accepts optional return value. Aliases: !!@
exit-program      End the current program. Aliases: quit-program, !!!
!pry              Start a Pry session on current self; this even works mid-expression.
whereami          Show the code context for the session. (whereami  shows  extra lines of code around the invocation line. Default: 5)
!                 Clear the input buffer. Useful if the parsing process goes wrong and you get stuck in the read loop.
show-input        Show the contents of the input buffer for the current multi-line expression.
amend-line        Amend a line of input in multi-line mode. Type `amend-line --help` for more information. Aliases %
play              Play back a string or a method or a file as input. Type `play --help` for more information.
hist              Show and replay Readline history. Type `hist --help` for more info. Aliases: history
.  All text following a '.' is forwarded to the shell.
shell-mode        Toggle shell mode. Bring in pwd prompt and file completion.
cat               Show output of file FILE. Type `cat --help` for more information.
show-method       Show the source for METH. Type `show-method --help` for more info. Aliases: $, show-source
show-command      Show the source for CMD. Type `show-command --help` for more info.
edit              Invoke the default editor on a file. Type `edit --help` for more info
edit-method       Edit a method. Type `edit-method --help` for more info.

Thanks!

Documenting the Redmine API

Angelegt von suung Thu, 16 Jun 2011 11:36:00 GMT

DocumentationAPI

grep -rn --color --exclude-dir 'config/locales' --exclude-dir 'vendor' --exclude-dir 'public' --exclude-dir 'log' 'api' .

SETTINGS

./config/settings.yml:91:sys_api_enabled:
./config/settings.yml:93:sys_api_key:
./config/settings.yml:131:mail_handler_api_enabled:
./config/settings.yml:133:mail_handler_api_key:
./config/settings.yml:193:rest_api_enabled:

THE WORKFLOW

  1. > Mime Type 'api' registered
  2. > respond_to.api
  3. > Template Handler 'api' registered
  4. > Builder.for(params[:format])

Supported Formats

  • json
  • xml

The global api - methods

./config/initializers/10-patches.rb:99: def api(&block)

# registers the mime type for api
module ActionController
  module MimeResponds
    class Responder
      def api(&block)
        any(:xml, :json, &block)
      end
    end
  end
end

./app/helpers/application_helper.rb:922: def api_meta(options)

Including Relations

./app/helpers/application_helper.rb:911: def include_in_api_response?(arg)

  # Returns true if arg is expected in the API response
  def include_in_api_response?(arg)
    unless @included_in_api_response
      param = params[:include]
      @included_in_api_response = param.is_a?(Array) ? param.collect(&:to_s) : param.to_s.split(',')
      @included_in_api_response.collect!(&:strip)
    end
    @included_in_api_response.include?(arg.to_s)
  end

 

Where is it

./app/views/issues/show.api.rsb:  render_api_issue_children(@issue, api) if include_in_api_response?('children')
./app/views/issues/show.api.rsb:  end if include_in_api_response?('relations') && @relations.present?
./app/views/issues/show.api.rsb:  end if include_in_api_response?('changesets') && User.current.allowed_to?(:view_changesets, @project)
./app/views/issues/show.api.rsb:  end if include_in_api_response?('journals')
./app/views/projects/show.api.rsb:  end if include_in_api_response?('trackers')
./app/views/users/show.api.rsb:  end if include_in_api_response?('memberships') && @memberships

 

Building the Response

/lib/redmine/views/api_template_handler.rb:24

      def compile(template) 
        "Redmine::Views::Builders.for(params[:format]) do |api|; #{template.source}; self.output_buffer = api.output; end" 
      end

 

The authentication system

User

/app/models/user.rb:52: has_one :api_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='api'"

  has_one :rss_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='feeds'" 
  has_one :api_token, :dependent => :destroy, :class_name => 'Token', :conditions => "action='api'" 

./app/models/user.rb:246: def api_key
./app/models/user.rb:247: token = self.api_token || self.create_api_token(:action => 'api')

  def api_key
    token = self.api_token || self.create_api_token(:action => 'api')
    token.value
  end

 

./app/models/user.rb:294: def self.find_by_api_key(key)

  def self.find_by_api_key(key)
    token = Token.find_by_action_and_value('api', key)
    token && token.user.active? ? token.user : nil
  end

API enabled controllers (06/16/2011)

/timelog_controller.rb
/projects_controller.rb
/news_controller.rb
/issues_controller.rb
/users_controller.rb

# IssuesController#index

      respond_to do |format|
        format.html { render :template => 'issues/index.rhtml', :layout => !request.xhr? }
        # HERE
        format.api
        format.atom { render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}") }
        format.csv  { send_data(issues_to_csv(@issues, @project), :type => 'text/csv; header=present', :filename => 'export.csv') }
        format.pdf  { send_data(issues_to_pdf(@issues, @project, @query), :type => 'application/pdf', :filename => 'export.pdf') }
      end

Builder Templates

./app/views/issues/index.api.rsb

api.array :issues, api_meta(:total_count => @issue_count, :offset => @offset, :limit => @limit) do
  @issues.each do |issue|
    api.issue do
      api.id issue.id
      api.project(:id => issue.project_id, :name => issue.project.name) unless issue.project.nil?
      api.tracker(:id => issue.tracker_id, :name => issue.tracker.name) unless issue.tracker.nil?
      api.done_ratio     issue.done_ratio
      api.estimated_hours issue.estimated_hours

      render_api_custom_values issue.custom_field_values, api

      api.created_on issue.created_on
      api.updated_on issue.updated_on
    end
  end
end

 

./app/helpers/custom_fields_helper.rb:109: def render_api_custom_values(custom_values, api)

  # Renders the custom_values in api views
  def render_api_custom_values(custom_values, api)
    api.array :custom_fields do
      custom_values.each do |custom_value|
        api.custom_field :id => custom_value.custom_field_id, :name => custom_value.custom_field.name do
          api.value custom_value.value
        end
      end
    end unless custom_values.empty?
  end

Jquery UI Dialog and multiple Dialogs on one page / Jquery UI Dialog only opens once

Angelegt von andi Fri, 10 Jun 2011 21:26:00 GMT

When you work with the Jquery UI Dialog Widet, you might come across an issue with the dialog only showing once. This happens because once you initialize the dom element the element that you use for the dialog gets removed from the dome, and stored into the Dialog instance. One of the core Jquery UI developers describes an easy solution for this issue in his blog. But the described way to solve the issue still needs to be patched, when you have multiple dialogs on the page, because from the link that you use to open the dialog, is no easy way to determine which of the already initialized dialogs to open.

What i did below is to give each dialog link an unique id (in this case “dialog_#{someactiverecordobject.id}”, and use it to ‘name’ the dialogs and therefore be able to know which one to open.

$(function() {
        var dialogs = {}
        $('.dialog').each(function() {
                var dialog_id = $(this).prev('.dialog_link').attr('id');
                dialogs[dialog_id] = $(this).dialog({autoOpen: false, title: '<b>Details</b>'});
            });
        $('.event_details_link').click(function() {
                dialogs[$(this).attr('id')].dialog('open');
                return false;
            });
    });

Stubbing, Mocking, Testing HTTP Requests in RSPEC with Webmock

Angelegt von suung Tue, 07 Jun 2011 11:49:00 GMT

Rails 3 Lernen mit d:evolute

Angelegt von suung Mon, 06 Jun 2011 11:21:00 GMT

Aus den Archiven unserer Software - Abteilung d:evolute ein Einsteiger - Guide fuer Rails (3)

- rails_lernen.pdf

Compound Index in Rals and a lot more SQL explanation

Angelegt von suung Sun, 15 May 2011 12:29:00 GMT

Doing a research on compound indices in Rails3, i found this article with a loot of cool information, benchmarks end detailled explanation of different queries (using indices)

Friendly No-SQL - like ORM for MySQL, Serialization and Custom Fields

Angelegt von suung Sun, 24 Apr 2011 16:47:00 GMT

We at devolute and brueckenschlaeger work on technologies, that allow you to have your SQL - Databases administered as schemaless as possible.

Consider the typical case of a Feedback form or a simple Survey.

You just don't wanna create a new table for every type of questionnaire. Plus performance (on read operation) is not the main problem here., you want to focus on fast write and later export your data and analyze it somewhat.

There are two basic technologies, I know to do that:

  • Serialization
  • A Thing called 'Custom Fields'


Serialization let's you simply dump your schema into a text column. Try it, it does not hurt. With rails it's dead simple anyway.
Drawbacks and pitfalls exist :)

Custom Fields - well, take a look at redmine. The 'Issues' are like a schemaless model with a bit basic schema (one could leave that). And now you have fields and field-object relation.

So the basic schema less database in Rails would look like this:

<pre>

 class Thing < ActiveRecord::Base
    has_many :properties, :through => :relations   
end
class Relation < ActiveRecord::Base
  belongs_to :thing
  belongs_to :property
end
class Property < ActiveRecord:;Base
  has_many :things, :through => :relations
end

</pre>

As you see, now every property could exist in several things. You might not want that, but Rails doesn't have has_one .. :through. Work around it.

In Property you would have two columns:

  • name: string
  • data: text


I think you get the idea.

 

Now, to the topic - just found this: http://www.rubyinside.com/friendly-easy-schemaless-nosql-data-storage-with-mysql-in-ruby-2908.html

OneAim Content Management Released

Angelegt von suung Tue, 19 Apr 2011 20:31:00 GMT

Finally I released the Content Management used on OneAim.

OneAim is the following:

a) There is one aim

b) Projects having that one aim can be open or finished.

Great, what?
 

As the time goes by and the project becomes more and more old (Rails 2) I release it. 

https://github.com/suung/oneaim

How to set up Compass on Rails 1

Angelegt von suung Tue, 25 Jan 2011 12:19:00 GMT

Because no one in my team ever wrote it down, i will do that now for you:

It's pretty easy:

 

compass create myproject
mate myproject
compass watch myproject

compass init rails /path/to/myrailsproject

with blueprint 

compass init rails /path/to/myrailsproject --using blueprint/semantic