15 |
16 | @property (strong, nonatomic) UIWindow *window;
17 |
18 | @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
19 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
20 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
21 |
22 | - (void)saveContext;
23 | - (NSURL *)applicationDocumentsDirectory;
24 |
25 | #define ApplicationDelegate ((LDTAppDelegate *)[UIApplication sharedApplication].delegate)
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/Gemfile:
--------------------------------------------------------------------------------
1 | source 'http://rubygems.org'
2 |
3 | gem 'rails', '3.1.1'
4 |
5 | # Bundle edge Rails instead:
6 | # gem 'rails', :git => 'git://github.com/rails/rails.git'
7 |
8 | gem 'sqlite3'
9 |
10 |
11 | # Gems used only for assets and not required
12 | # in production environments by default.
13 | group :assets do
14 | gem 'sass-rails', '~> 3.1.4'
15 | gem 'coffee-rails', '~> 3.1.1'
16 | gem 'uglifier', '>= 1.0.3'
17 | end
18 |
19 | gem 'jquery-rails'
20 |
21 | # To use ActiveModel has_secure_password
22 | # gem 'bcrypt-ruby', '~> 3.0.0'
23 |
24 | # Use unicorn as the web server
25 | # gem 'unicorn'
26 |
27 | # Deploy with Capistrano
28 | # gem 'capistrano'
29 |
30 | # To use debugger
31 | # gem 'ruby-debug19', :require => 'ruby-debug'
32 |
33 | group :test do
34 | # Pretty printed test output
35 | gem 'turn', :require => false
36 | gem "minitest"
37 | end
38 |
39 | gem 'ffaker'
40 | gem 'random_data'
41 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2.xcworkspace/xcuserdata/shane.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEWorkspaceUserSettings_BuildLocationStyle
6 | 0
7 | IDEWorkspaceUserSettings_BuildSubfolderNameStyle
8 | 0
9 | IDEWorkspaceUserSettings_DerivedDataLocationStyle
10 | 0
11 | IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges
12 |
13 | IDEWorkspaceUserSettings_IssueFilterStyle
14 | 0
15 | IDEWorkspaceUserSettings_LiveSourceIssuesEnabled
16 |
17 | IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges
18 |
19 | IDEWorkspaceUserSettings_SnapshotLocationStyle
20 | 0
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/app/views/posts/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_for(@post) do |f| %>
2 | <% if @post.errors.any? %>
3 |
4 |
<%= pluralize(@post.errors.count, "error") %> prohibited this post from being saved:
5 |
6 |
7 | <% @post.errors.full_messages.each do |msg| %>
8 | <%= msg %>
9 | <% end %>
10 |
11 |
12 | <% end %>
13 |
14 |
15 | <%= f.label :title %>
16 | <%= f.text_field :title %>
17 |
18 |
19 | <%= f.label :body %>
20 | <%= f.text_area :body %>
21 |
22 |
23 | <%= f.label :topic %>
24 | <%= f.select(:topic_id,Topic.all.collect {|topic|
25 | [topic.title,topic.id]},:prompt => true, :include_blank => true) %>
26 |
27 |
28 | <%= f.label :author %>
29 | <%= f.select(:author_id,Author.all.collect {|author|
30 | [author.username,author.id]},:prompt => true, :include_blank => true) %>
31 |
32 |
33 | <%= f.submit %>
34 |
35 | <% end %>
36 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Ldtrkpoc2svr::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Log error messages when you accidentally call methods on nil.
10 | config.whiny_nils = true
11 |
12 | # Show full error reports and disable caching
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send
17 | config.action_mailer.raise_delivery_errors = false
18 |
19 | # Print deprecation notices to the Rails logger
20 | config.active_support.deprecation = :log
21 |
22 | # Only use best-standards-support built into browsers
23 | config.action_dispatch.best_standards_support = :builtin
24 |
25 | # Do not compress assets
26 | config.assets.compress = false
27 |
28 | # Expands the lines which load the assets
29 | config.assets.debug = true
30 | end
31 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/test/functional/posts_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class PostsControllerTest < ActionController::TestCase
4 | setup do
5 | @post = posts(:one)
6 | end
7 |
8 | test "should get index" do
9 | get :index
10 | assert_response :success
11 | assert_not_nil assigns(:posts)
12 | end
13 |
14 | test "should get new" do
15 | get :new
16 | assert_response :success
17 | end
18 |
19 | test "should create post" do
20 | assert_difference('Post.count') do
21 | post :create, post: @post.attributes
22 | end
23 |
24 | assert_redirected_to post_path(assigns(:post))
25 | end
26 |
27 | test "should show post" do
28 | get :show, id: @post.to_param
29 | assert_response :success
30 | end
31 |
32 | test "should get edit" do
33 | get :edit, id: @post.to_param
34 | assert_response :success
35 | end
36 |
37 | test "should update post" do
38 | put :update, id: @post.to_param, post: @post.attributes
39 | assert_redirected_to post_path(assigns(:post))
40 | end
41 |
42 | test "should destroy post" do
43 | assert_difference('Post.count', -1) do
44 | delete :destroy, id: @post.to_param
45 | end
46 |
47 | assert_redirected_to posts_path
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/test/functional/users_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class UsersControllerTest < ActionController::TestCase
4 | setup do
5 | @user = users(:one)
6 | end
7 |
8 | test "should get index" do
9 | get :index
10 | assert_response :success
11 | assert_not_nil assigns(:users)
12 | end
13 |
14 | test "should get new" do
15 | get :new
16 | assert_response :success
17 | end
18 |
19 | test "should create user" do
20 | assert_difference('User.count') do
21 | post :create, user: @user.attributes
22 | end
23 |
24 | assert_redirected_to user_path(assigns(:user))
25 | end
26 |
27 | test "should show user" do
28 | get :show, id: @user.to_param
29 | assert_response :success
30 | end
31 |
32 | test "should get edit" do
33 | get :edit, id: @user.to_param
34 | assert_response :success
35 | end
36 |
37 | test "should update user" do
38 | put :update, id: @user.to_param, user: @user.attributes
39 | assert_redirected_to user_path(assigns(:user))
40 | end
41 |
42 | test "should destroy user" do
43 | assert_difference('User.count', -1) do
44 | delete :destroy, id: @user.to_param
45 | end
46 |
47 | assert_redirected_to users_path
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/test/functional/topics_controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'test_helper'
2 |
3 | class TopicsControllerTest < ActionController::TestCase
4 | setup do
5 | @topic = topics(:one)
6 | end
7 |
8 | test "should get index" do
9 | get :index
10 | assert_response :success
11 | assert_not_nil assigns(:topics)
12 | end
13 |
14 | test "should get new" do
15 | get :new
16 | assert_response :success
17 | end
18 |
19 | test "should create topic" do
20 | assert_difference('Topic.count') do
21 | post :create, topic: @topic.attributes
22 | end
23 |
24 | assert_redirected_to topic_path(assigns(:topic))
25 | end
26 |
27 | test "should show topic" do
28 | get :show, id: @topic.to_param
29 | assert_response :success
30 | end
31 |
32 | test "should get edit" do
33 | get :edit, id: @topic.to_param
34 | assert_response :success
35 | end
36 |
37 | test "should update topic" do
38 | put :update, id: @topic.to_param, topic: @topic.attributes
39 | assert_redirected_to topic_path(assigns(:topic))
40 | end
41 |
42 | test "should destroy topic" do
43 | assert_difference('Topic.count', -1) do
44 | delete :destroy, id: @topic.to_param
45 | end
46 |
47 | assert_redirected_to topics_path
48 | end
49 | end
50 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/app/assets/stylesheets/scaffolds.css.scss:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #fff;
3 | color: #333;
4 | font-family: verdana, arial, helvetica, sans-serif;
5 | font-size: 13px;
6 | line-height: 18px; }
7 |
8 | p, ol, ul, td {
9 | font-family: verdana, arial, helvetica, sans-serif;
10 | font-size: 13px;
11 | line-height: 18px; }
12 |
13 | pre {
14 | background-color: #eee;
15 | padding: 10px;
16 | font-size: 11px; }
17 |
18 | a {
19 | color: #000;
20 | &:visited {
21 | color: #666; }
22 | &:hover {
23 | color: #fff;
24 | background-color: #000; } }
25 |
26 | div {
27 | &.field, &.actions {
28 | margin-bottom: 10px; } }
29 |
30 | #notice {
31 | color: green; }
32 |
33 | .field_with_errors {
34 | padding: 2px;
35 | background-color: red;
36 | display: table; }
37 |
38 | #error_explanation {
39 | width: 450px;
40 | border: 2px solid red;
41 | padding: 7px;
42 | padding-bottom: 0;
43 | margin-bottom: 20px;
44 | background-color: #f0f0f0;
45 | h2 {
46 | text-align: left;
47 | font-weight: bold;
48 | padding: 5px 5px 5px 15px;
49 | font-size: 12px;
50 | margin: -7px;
51 | margin-bottom: 0px;
52 | background-color: #c00;
53 | color: #fff; }
54 | ul li {
55 | font-size: 12px;
56 | list-style: square; } }
57 |
--------------------------------------------------------------------------------
/iOS/core_data_empty/cdstuff/cdstuff/cdstuff-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIconFiles
12 |
13 | CFBundleIdentifier
14 | com.lottadot.${PRODUCT_NAME:rfc1034identifier}
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | ${PRODUCT_NAME}
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | 1.0
23 | CFBundleSignature
24 | ????
25 | CFBundleVersion
26 | 1.0
27 | LSRequiresIPhoneOS
28 |
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/ldtrkpoc2-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIconFiles
12 |
13 | CFBundleIdentifier
14 | com.lottadot.${PRODUCT_NAME:rfc1034identifier}
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | ${PRODUCT_NAME}
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | 1.0
23 | CFBundleSignature
24 | ????
25 | CFBundleVersion
26 | 1.0
27 | LSRequiresIPhoneOS
28 |
29 | UIMainStoryboardFile
30 | MainStoryboard
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 |
9 | lottadot = Author.create(username: 'lottadot', email:'shane@lottadot.com');
10 | john_doe = Author.create(username: 'johndoe', email:'johndoe@lottadot.com');
11 | restkit_topic = Topic.create(title: 'restkit', body: 'this is the restkit topic');
12 | lottadot_topic = Topic.create(title: 'lottadot', body: 'this is the lottadot topic');
13 | ios_topic = Topic.create(title: 'iOS', body: 'this is the iOS topic');
14 | objc_topic = Topic.create(title: 'objc', body: 'this is the objc topic');
15 |
16 | restkit_post = Post.create(title: 'reskit rocks', body: 'this is the restkit post', author: lottadot, topic: restkit_topic);
17 | lottadot_post = Post.create(title: 'lottadot rocks', body: 'this is the lottadot post', author: lottadot, topic: lottadot_topic);
18 |
19 | ios_post = Post.create(title: 'ios rocks', body: 'this is the ios post', author: john_doe, topic: ios_topic);
20 | objc_post = Post.create(title: 'objc rocks', body: 'this is the objc post', author: john_doe, topic: objc_topic);
21 |
22 | restkit_post2 = Post.create(title: 'reskit rolls', body: 'this is another restkit post', author: john_doe, topic: restkit_topic);
--------------------------------------------------------------------------------
/ldtrkpoc2svr/lib/tasks/load.rake:
--------------------------------------------------------------------------------
1 | # http://stackoverflow.com/questions/3782177/rake-task-to-add-default-data
2 | # RAILS_ENV="development" rake myapp:data:load
3 | # problems? try RAILS_ENV="development" rake myapp:data:load --trace
4 | require File.join(File.dirname(__FILE__), '../../config/environment')
5 |
6 | namespace :myapp do
7 | namespace :load do
8 |
9 | # Swiped from ActiveRecord migrations.rb
10 | def announce(message)
11 | length = [0, 75 - message.length].max
12 | puts "== %s %s" % [message, "=" * length]
13 | end
14 |
15 | desc "Creates n number random topics using the Random Data gem, defaults to 150"
16 | task :random_topics, [:n] => :environment do |t, args|
17 | begin
18 | n = args.n.to_i < 1 ? 150 : args.n.to_i
19 | require 'ffaker'
20 | require 'random_data'
21 | time = Benchmark.measure do
22 | n.times do |i|
23 | topictitle = Faker::Company.name
24 | topicbody = Faker::Lorem.paragraph
25 |
26 | catch do
27 | t = Topic.new(:title => topictitle, :body => topicbody)
28 | t.save!
29 | puts "%6d: %15s" % [(i+1), t.title]
30 | end
31 | end
32 | end
33 | announce "Loaded %6d topics in (%2dm %2.0fs)" % [n, *time.real.divmod(60)]
34 | rescue LoadError
35 | puts "This rake task requires random_data. To install, run this command:\n\n sudo gem install random_data\n\n"
36 | end
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/db/schema.rb:
--------------------------------------------------------------------------------
1 | # encoding: UTF-8
2 | # This file is auto-generated from the current state of the database. Instead
3 | # of editing this file, please use the migrations feature of Active Record to
4 | # incrementally modify your database, and then regenerate this schema definition.
5 | #
6 | # Note that this schema.rb definition is the authoritative source for your
7 | # database schema. If you need to create the application database on another
8 | # system, you should be using db:schema:load, not running all the migrations
9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10 | # you'll amass, the slower it'll run and the greater likelihood for issues).
11 | #
12 | # It's strongly recommended to check this file into your version control system.
13 |
14 | ActiveRecord::Schema.define(:version => 20111209005001) do
15 |
16 | create_table "posts", :force => true do |t|
17 | t.string "title"
18 | t.string "body"
19 | t.integer "topic_id"
20 | t.integer "author_id"
21 | t.datetime "created_at"
22 | t.datetime "updated_at"
23 | end
24 |
25 | add_index "posts", ["author_id"], :name => "index_posts_on_author_id"
26 | add_index "posts", ["topic_id"], :name => "index_posts_on_topic_id"
27 |
28 | create_table "topics", :force => true do |t|
29 | t.string "title"
30 | t.string "body"
31 | t.datetime "created_at"
32 | t.datetime "updated_at"
33 | end
34 |
35 | create_table "users", :force => true do |t|
36 | t.string "username"
37 | t.string "email"
38 | t.datetime "created_at"
39 | t.datetime "updated_at"
40 | end
41 |
42 | end
43 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Ldtrkpoc2svr::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Configure static asset server for tests with Cache-Control for performance
11 | config.serve_static_assets = true
12 | config.static_cache_control = "public, max-age=3600"
13 |
14 | # Log error messages when you accidentally call methods on nil
15 | config.whiny_nils = true
16 |
17 | # Show full error reports and disable caching
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 | config.action_mailer.delivery_method = :test
31 |
32 | # Use SQL instead of Active Record's schema dumper when creating the test database.
33 | # This is necessary if your schema can't be completely dumped by the schema dumper,
34 | # like if you have constraints or database-specific column types
35 | # config.active_record.schema_format = :sql
36 |
37 | # Print deprecation notices to the stderr
38 | config.active_support.deprecation = :stderr
39 | end
40 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/.rvmrc:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # This is an RVM Project .rvmrc file, used to automatically load the ruby
4 | # development environment upon cd'ing into the directory
5 |
6 | # First we specify our desired [@], the @gemset name is optional.
7 | environment_id="ruby-1.9.2-p290@ldtrkpoc2svr"
8 |
9 | #
10 | # Uncomment following line if you want options to be set only for given project.
11 | #
12 | # PROJECT_JRUBY_OPTS=( --1.9 )
13 |
14 | #
15 | # First we attempt to load the desired environment directly from the environment
16 | # file. This is very fast and efficient compared to running through the entire
17 | # CLI and selector. If you want feedback on which environment was used then
18 | # insert the word 'use' after --create as this triggers verbose mode.
19 | #
20 | if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
21 | && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
22 | then
23 | \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
24 |
25 | if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
26 | then
27 | . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
28 | fi
29 | else
30 | # If the environment file has not yet been created, use the RVM CLI to select.
31 | if ! rvm --create use "$environment_id"
32 | then
33 | echo "Failed to create RVM environment '${environment_id}'."
34 | exit 1
35 | fi
36 | fi
37 |
38 | #
39 | # If you use an RVM gemset file to install a list of gems (*.gems), you can have
40 | # it be automatically loaded. Uncomment the following and adjust the filename if
41 | # necessary.
42 | #
43 | # filename=".gems"
44 | # if [[ -s "$filename" ]]
45 | # then
46 | # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
47 | # fi
48 |
49 | # If you use bundler, this might be useful to you:
50 | # if command -v bundle && [[ -s Gemfile ]]
51 | # then
52 | # bundle
53 | # fi
54 |
55 |
56 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/app/controllers/users_controller.rb:
--------------------------------------------------------------------------------
1 | class UsersController < ApplicationController
2 | # GET /users
3 | # GET /users.json
4 | def index
5 | @users = User.all
6 |
7 | respond_to do |format|
8 | format.html # index.html.erb
9 | format.json { render json: @users }
10 | end
11 | end
12 |
13 | # GET /users/1
14 | # GET /users/1.json
15 | def show
16 | @user = User.find(params[:id])
17 |
18 | respond_to do |format|
19 | format.html # show.html.erb
20 | format.json { render json: @user }
21 | end
22 | end
23 |
24 | # GET /users/new
25 | # GET /users/new.json
26 | def new
27 | @user = User.new
28 |
29 | respond_to do |format|
30 | format.html # new.html.erb
31 | format.json { render json: @user }
32 | end
33 | end
34 |
35 | # GET /users/1/edit
36 | def edit
37 | @user = User.find(params[:id])
38 | end
39 |
40 | # POST /users
41 | # POST /users.json
42 | def create
43 | @user = User.new(params[:user])
44 |
45 | respond_to do |format|
46 | if @user.save
47 | format.html { redirect_to @user, notice: 'User was successfully created.' }
48 | format.json { render json: @user, status: :created, location: @user }
49 | else
50 | format.html { render action: "new" }
51 | format.json { render json: @user.errors, status: :unprocessable_entity }
52 | end
53 | end
54 | end
55 |
56 | # PUT /users/1
57 | # PUT /users/1.json
58 | def update
59 | @user = User.find(params[:id])
60 |
61 | respond_to do |format|
62 | if @user.update_attributes(params[:user])
63 | format.html { redirect_to @user, notice: 'User was successfully updated.' }
64 | format.json { head :ok }
65 | else
66 | format.html { render action: "edit" }
67 | format.json { render json: @user.errors, status: :unprocessable_entity }
68 | end
69 | end
70 | end
71 |
72 | # DELETE /users/1
73 | # DELETE /users/1.json
74 | def destroy
75 | @user = User.find(params[:id])
76 | @user.destroy
77 |
78 | respond_to do |format|
79 | format.html { redirect_to users_url }
80 | format.json { head :ok }
81 | end
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | require 'rails/all'
4 |
5 | if defined?(Bundler)
6 | # If you precompile assets before deploying to production, use this line
7 | Bundler.require(*Rails.groups(:assets => %w(development test)))
8 | # If you want your assets lazily compiled in production, use this line
9 | # Bundler.require(:default, :assets, Rails.env)
10 | end
11 |
12 | module Ldtrkpoc2svr
13 | class Application < Rails::Application
14 | # Settings in config/environments/* take precedence over those specified here.
15 | # Application configuration should go into files in config/initializers
16 | # -- all .rb files in that directory are automatically loaded.
17 |
18 | # Custom directories with classes and modules you want to be autoloadable.
19 | # config.autoload_paths += %W(#{config.root}/extras)
20 |
21 | # Only load the plugins named here, in the order given (default is alphabetical).
22 | # :all can be used as a placeholder for all plugins not explicitly named.
23 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24 |
25 | # Activate observers that should always be running.
26 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27 |
28 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30 | # config.time_zone = 'Central Time (US & Canada)'
31 |
32 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34 | # config.i18n.default_locale = :de
35 |
36 | # Configure the default encoding used in templates for Ruby 1.9.
37 | config.encoding = "utf-8"
38 |
39 | # Configure sensitive parameters which will be filtered from the log file.
40 | config.filter_parameters += [:password]
41 |
42 | # Enable the asset pipeline
43 | config.assets.enabled = true
44 |
45 | # Version of your assets, change this if you want to expire all your assets
46 | config.assets.version = '1.0'
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/app/controllers/topics_controller.rb:
--------------------------------------------------------------------------------
1 | class TopicsController < ApplicationController
2 | # GET /topics
3 | # GET /topics.json
4 | def index
5 | @topics = Topic.all
6 |
7 | respond_to do |format|
8 | format.html # index.html.erb
9 | format.json { render json: @topics }
10 | end
11 | end
12 |
13 | # GET /topics/1
14 | # GET /topics/1.json
15 | def show
16 | @topic = Topic.find(params[:id])
17 |
18 | respond_to do |format|
19 | format.html # show.html.erb
20 | format.json { render json: @topic }
21 | end
22 | end
23 |
24 | # GET /topics/new
25 | # GET /topics/new.json
26 | def new
27 | @topic = Topic.new
28 |
29 | respond_to do |format|
30 | format.html # new.html.erb
31 | format.json { render json: @topic }
32 | end
33 | end
34 |
35 | # GET /topics/1/edit
36 | def edit
37 | @topic = Topic.find(params[:id])
38 | end
39 |
40 | # POST /topics
41 | # POST /topics.json
42 | def create
43 | @topic = Topic.new(params[:topic])
44 |
45 | respond_to do |format|
46 | if @topic.save
47 | format.html { redirect_to @topic, notice: 'Topic was successfully created.' }
48 | format.json { render json: @topic, status: :created, location: @topic }
49 | else
50 | format.html { render action: "new" }
51 | format.json { render json: @topic.errors, status: :unprocessable_entity }
52 | end
53 | end
54 | end
55 |
56 | # PUT /topics/1
57 | # PUT /topics/1.json
58 | def update
59 | @topic = Topic.find(params[:id])
60 |
61 | respond_to do |format|
62 | if @topic.update_attributes(params[:topic])
63 | format.html { redirect_to @topic, notice: 'Topic was successfully updated.' }
64 | format.json { head :ok }
65 | else
66 | format.html { render action: "edit" }
67 | format.json { render json: @topic.errors, status: :unprocessable_entity }
68 | end
69 | end
70 | end
71 |
72 | # DELETE /topics/1
73 | # DELETE /topics/1.json
74 | def destroy
75 | @topic = Topic.find(params[:id])
76 | @topic.destroy
77 |
78 | respond_to do |format|
79 | format.html { redirect_to topics_url }
80 | format.json { head :ok }
81 | end
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Ldtrkpoc2svr::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # Code is not reloaded between requests
5 | config.cache_classes = true
6 |
7 | # Full error reports are disabled and caching is turned on
8 | config.consider_all_requests_local = false
9 | config.action_controller.perform_caching = true
10 |
11 | # Disable Rails's static asset server (Apache or nginx will already do this)
12 | config.serve_static_assets = false
13 |
14 | # Compress JavaScripts and CSS
15 | config.assets.compress = true
16 |
17 | # Don't fallback to assets pipeline if a precompiled asset is missed
18 | config.assets.compile = false
19 |
20 | # Generate digests for assets URLs
21 | config.assets.digest = true
22 |
23 | # Defaults to Rails.root.join("public/assets")
24 | # config.assets.manifest = YOUR_PATH
25 |
26 | # Specifies the header that your server uses for sending files
27 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
29 |
30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
31 | # config.force_ssl = true
32 |
33 | # See everything in the log (default is :info)
34 | # config.log_level = :debug
35 |
36 | # Use a different logger for distributed setups
37 | # config.logger = SyslogLogger.new
38 |
39 | # Use a different cache store in production
40 | # config.cache_store = :mem_cache_store
41 |
42 | # Enable serving of images, stylesheets, and JavaScripts from an asset server
43 | # config.action_controller.asset_host = "http://assets.example.com"
44 |
45 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
46 | # config.assets.precompile += %w( search.js )
47 |
48 | # Disable delivery errors, bad email addresses will be ignored
49 | # config.action_mailer.raise_delivery_errors = false
50 |
51 | # Enable threaded mode
52 | # config.threadsafe!
53 |
54 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
55 | # the I18n.default_locale when a translation can not be found)
56 | config.i18n.fallbacks = true
57 |
58 | # Send deprecation notices to registered listeners
59 | config.active_support.deprecation = :notify
60 | end
61 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/Generated/_Topic.m:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This file is machine-generated and constantly overwritten.
2 | // Make changes to Topic.m instead.
3 |
4 | #import "_Topic.h"
5 |
6 | const struct TopicAttributes TopicAttributes = {
7 | .body = @"body",
8 | .title = @"title",
9 | .topicID = @"topicID",
10 | };
11 |
12 | const struct TopicRelationships TopicRelationships = {
13 | .posts = @"posts",
14 | };
15 |
16 | const struct TopicFetchedProperties TopicFetchedProperties = {
17 | };
18 |
19 | @implementation TopicID
20 | @end
21 |
22 | @implementation _Topic
23 |
24 | + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ {
25 | NSParameterAssert(moc_);
26 | return [NSEntityDescription insertNewObjectForEntityForName:@"Topic" inManagedObjectContext:moc_];
27 | }
28 |
29 | + (NSString*)entityName {
30 | return @"Topic";
31 | }
32 |
33 | + (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ {
34 | NSParameterAssert(moc_);
35 | return [NSEntityDescription entityForName:@"Topic" inManagedObjectContext:moc_];
36 | }
37 |
38 | - (TopicID*)objectID {
39 | return (TopicID*)[super objectID];
40 | }
41 |
42 | + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
43 | NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
44 |
45 | if ([key isEqualToString:@"topicIDValue"]) {
46 | NSSet *affectingKey = [NSSet setWithObject:@"topicID"];
47 | keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey];
48 | }
49 |
50 | return keyPaths;
51 | }
52 |
53 |
54 |
55 |
56 | @dynamic body;
57 |
58 |
59 |
60 |
61 |
62 |
63 | @dynamic title;
64 |
65 |
66 |
67 |
68 |
69 |
70 | @dynamic topicID;
71 |
72 |
73 |
74 | - (short)topicIDValue {
75 | NSNumber *result = [self topicID];
76 | return [result shortValue];
77 | }
78 |
79 | - (void)setTopicIDValue:(short)value_ {
80 | [self setTopicID:[NSNumber numberWithShort:value_]];
81 | }
82 |
83 | - (short)primitiveTopicIDValue {
84 | NSNumber *result = [self primitiveTopicID];
85 | return [result shortValue];
86 | }
87 |
88 | - (void)setPrimitiveTopicIDValue:(short)value_ {
89 | [self setPrimitiveTopicID:[NSNumber numberWithShort:value_]];
90 | }
91 |
92 |
93 |
94 |
95 |
96 | @dynamic posts;
97 |
98 |
99 | - (NSMutableSet*)postsSet {
100 | [self willAccessValueForKey:@"posts"];
101 |
102 | NSMutableSet *result = (NSMutableSet*)[self mutableSetValueForKey:@"posts"];
103 |
104 | [self didAccessValueForKey:@"posts"];
105 | return result;
106 | }
107 |
108 |
109 |
110 |
111 |
112 |
113 | @end
114 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/Generated/_Topic.h:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This file is machine-generated and constantly overwritten.
2 | // Make changes to Topic.h instead.
3 |
4 | #import
5 | #import "RootManagedObjectClass.h"
6 |
7 | extern const struct TopicAttributes {
8 | __unsafe_unretained NSString *body;
9 | __unsafe_unretained NSString *title;
10 | __unsafe_unretained NSString *topicID;
11 | } TopicAttributes;
12 |
13 | extern const struct TopicRelationships {
14 | __unsafe_unretained NSString *posts;
15 | } TopicRelationships;
16 |
17 | extern const struct TopicFetchedProperties {
18 | } TopicFetchedProperties;
19 |
20 | @class Post;
21 |
22 |
23 |
24 |
25 |
26 | @interface TopicID : NSManagedObjectID {}
27 | @end
28 |
29 | @interface _Topic : RootManagedObjectClass {}
30 | + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_;
31 | + (NSString*)entityName;
32 | + (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_;
33 | - (TopicID*)objectID;
34 |
35 |
36 |
37 |
38 | @property (nonatomic, strong) NSString *body;
39 |
40 |
41 | //- (BOOL)validateBody:(id*)value_ error:(NSError**)error_;
42 |
43 |
44 |
45 |
46 | @property (nonatomic, strong) NSString *title;
47 |
48 |
49 | //- (BOOL)validateTitle:(id*)value_ error:(NSError**)error_;
50 |
51 |
52 |
53 |
54 | @property (nonatomic, strong) NSNumber *topicID;
55 |
56 |
57 | @property short topicIDValue;
58 | - (short)topicIDValue;
59 | - (void)setTopicIDValue:(short)value_;
60 |
61 | //- (BOOL)validateTopicID:(id*)value_ error:(NSError**)error_;
62 |
63 |
64 |
65 |
66 |
67 | @property (nonatomic, strong) NSSet* posts;
68 |
69 | - (NSMutableSet*)postsSet;
70 |
71 |
72 |
73 |
74 | @end
75 |
76 | @interface _Topic (CoreDataGeneratedAccessors)
77 |
78 | - (void)addPosts:(NSSet*)value_;
79 | - (void)removePosts:(NSSet*)value_;
80 | - (void)addPostsObject:(Post*)value_;
81 | - (void)removePostsObject:(Post*)value_;
82 |
83 | @end
84 |
85 | @interface _Topic (CoreDataGeneratedPrimitiveAccessors)
86 |
87 |
88 | - (NSString*)primitiveBody;
89 | - (void)setPrimitiveBody:(NSString*)value;
90 |
91 |
92 |
93 |
94 | - (NSString*)primitiveTitle;
95 | - (void)setPrimitiveTitle:(NSString*)value;
96 |
97 |
98 |
99 |
100 | - (NSNumber*)primitiveTopicID;
101 | - (void)setPrimitiveTopicID:(NSNumber*)value;
102 |
103 | - (short)primitiveTopicIDValue;
104 | - (void)setPrimitiveTopicIDValue:(short)value_;
105 |
106 |
107 |
108 |
109 |
110 | - (NSMutableSet*)primitivePosts;
111 | - (void)setPrimitivePosts:(NSMutableSet*)value;
112 |
113 |
114 | @end
115 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/TopicEditorViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TopicEditorViewController.m
3 | // ldtrkpoc2
4 | //
5 | // Created by Shane Zatezalo on 12/15/11.
6 | // Copyright (c) 2011 Lottadot LLC. All rights reserved.
7 | //
8 |
9 | #import "TopicEditorViewController.h"
10 | #import "MyModelEntities.h"
11 | #import "TopicsTableViewController.h"
12 |
13 | @implementation TopicEditorViewController
14 |
15 | @synthesize topic, titleField, bodyText, topicsViewController;
16 |
17 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
18 | {
19 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
20 | if (self) {
21 | // Custom initialization
22 | }
23 | return self;
24 | }
25 |
26 | - (void)didReceiveMemoryWarning
27 | {
28 | // Releases the view if it doesn't have a superview.
29 | [super didReceiveMemoryWarning];
30 |
31 | // Release any cached data, images, etc that aren't in use.
32 | }
33 |
34 | #pragma mark - View lifecycle
35 |
36 | - (void)viewWillAppear:(BOOL)animated {
37 | [super viewWillAppear:animated];
38 | self.title = @"Edit Topic";
39 | self.titleField.text = self.topic.title;
40 | [self.titleField becomeFirstResponder];
41 | self.bodyText.text = self.topic.body;
42 | }
43 |
44 | - (void)viewWillDisappear:(BOOL)animated {
45 | [super viewWillDisappear:animated];
46 | [self.titleField resignFirstResponder];
47 | }
48 |
49 | - (void)viewDidUnload
50 | {
51 | [super viewDidUnload];
52 | //[[RKClient sharedClient].requestQueue cancelRequestsWithDelegate:self];
53 | }
54 |
55 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
56 | {
57 | // Return YES for supported orientations
58 | return (interfaceOrientation == UIInterfaceOrientationPortrait);
59 | }
60 |
61 | #pragma mark - Text Field Delegate Methods
62 |
63 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder];
64 | return YES;
65 | }
66 |
67 | - (void)textFieldDidEndEditing:(UITextField *)textField {
68 | self.topic.title = self.titleField.text;
69 | }
70 |
71 | - (void)textViewDidEndEditing:(UITextView *)textView {
72 | self.topic.body = self.bodyText.text;
73 | }
74 |
75 | #pragma mark - Actions
76 |
77 | - (IBAction)done:(UIBarButtonItem *)sender {
78 | self.topic.title = self.titleField.text;
79 | self.topic.body = self.bodyText.text;
80 | [self.topicsViewController finishedEditing:self.topic AndCancelled:NO];
81 | }
82 |
83 | - (IBAction)cancel:(UIBarButtonItem *)sender {
84 | [self.topicsViewController finishedEditing:self.topic AndCancelled:YES];
85 | }
86 |
87 | @end
88 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/Generated/_Author.m:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This file is machine-generated and constantly overwritten.
2 | // Make changes to Author.m instead.
3 |
4 | #import "_Author.h"
5 |
6 | const struct AuthorAttributes AuthorAttributes = {
7 | .authorID = @"authorID",
8 | .email = @"email",
9 | .userName = @"userName",
10 | };
11 |
12 | const struct AuthorRelationships AuthorRelationships = {
13 | .posts = @"posts",
14 | };
15 |
16 | const struct AuthorFetchedProperties AuthorFetchedProperties = {
17 | };
18 |
19 | @implementation AuthorID
20 | @end
21 |
22 | @implementation _Author
23 |
24 | + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ {
25 | NSParameterAssert(moc_);
26 | return [NSEntityDescription insertNewObjectForEntityForName:@"Author" inManagedObjectContext:moc_];
27 | }
28 |
29 | + (NSString*)entityName {
30 | return @"Author";
31 | }
32 |
33 | + (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ {
34 | NSParameterAssert(moc_);
35 | return [NSEntityDescription entityForName:@"Author" inManagedObjectContext:moc_];
36 | }
37 |
38 | - (AuthorID*)objectID {
39 | return (AuthorID*)[super objectID];
40 | }
41 |
42 | + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
43 | NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
44 |
45 | if ([key isEqualToString:@"authorIDValue"]) {
46 | NSSet *affectingKey = [NSSet setWithObject:@"authorID"];
47 | keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey];
48 | }
49 |
50 | return keyPaths;
51 | }
52 |
53 |
54 |
55 |
56 | @dynamic authorID;
57 |
58 |
59 |
60 | - (short)authorIDValue {
61 | NSNumber *result = [self authorID];
62 | return [result shortValue];
63 | }
64 |
65 | - (void)setAuthorIDValue:(short)value_ {
66 | [self setAuthorID:[NSNumber numberWithShort:value_]];
67 | }
68 |
69 | - (short)primitiveAuthorIDValue {
70 | NSNumber *result = [self primitiveAuthorID];
71 | return [result shortValue];
72 | }
73 |
74 | - (void)setPrimitiveAuthorIDValue:(short)value_ {
75 | [self setPrimitiveAuthorID:[NSNumber numberWithShort:value_]];
76 | }
77 |
78 |
79 |
80 |
81 |
82 | @dynamic email;
83 |
84 |
85 |
86 |
87 |
88 |
89 | @dynamic userName;
90 |
91 |
92 |
93 |
94 |
95 |
96 | @dynamic posts;
97 |
98 |
99 | - (NSMutableSet*)postsSet {
100 | [self willAccessValueForKey:@"posts"];
101 |
102 | NSMutableSet *result = (NSMutableSet*)[self mutableSetValueForKey:@"posts"];
103 |
104 | [self didAccessValueForKey:@"posts"];
105 | return result;
106 | }
107 |
108 |
109 |
110 |
111 |
112 |
113 | @end
114 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/PostEditorViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PostEditorViewController.m
3 | // ldtrkpoc2
4 | //
5 | // Created by Shane Zatezalo on 12/26/11.
6 | // Copyright (c) 2011 Lottadot LLC. All rights reserved.
7 | //
8 |
9 | #import "PostEditorViewController.h"
10 | #import "MyModelEntities.h"
11 | #import "PostsTableViewController.h"
12 |
13 | @implementation PostEditorViewController
14 |
15 | @synthesize post, titleField, bodyText, postsViewController;
16 |
17 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
18 | {
19 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
20 | if (self) {
21 | // Custom initialization
22 | }
23 | return self;
24 | }
25 |
26 | - (void)didReceiveMemoryWarning
27 | {
28 | // Releases the view if it doesn't have a superview.
29 | [super didReceiveMemoryWarning];
30 |
31 | // Release any cached data, images, etc that aren't in use.
32 | }
33 |
34 | #pragma mark - View lifecycle
35 |
36 | - (void)viewWillAppear:(BOOL)animated {
37 | [super viewWillAppear:animated];
38 | self.title = @"Edit Post";
39 | self.titleField.text = self.post.title;
40 | [self.titleField becomeFirstResponder];
41 | self.bodyText.text = self.post.body;
42 | }
43 |
44 | - (void)viewWillDisappear:(BOOL)animated {
45 | [super viewWillDisappear:animated];
46 | [self.titleField resignFirstResponder];
47 | }
48 |
49 | - (void)viewDidUnload
50 | {
51 | [super viewDidUnload];
52 | // Release any retained subviews of the main view.
53 | // e.g. self.myOutlet = nil;
54 | }
55 |
56 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
57 | {
58 | // Return YES for supported orientations
59 | return (interfaceOrientation == UIInterfaceOrientationPortrait);
60 | }
61 |
62 | #pragma mark - Text Field Delegate Methods
63 |
64 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder];
65 | return YES;
66 | }
67 |
68 | - (void)textFieldDidEndEditing:(UITextField *)textField {
69 | self.post.title = self.titleField.text;
70 | }
71 |
72 | - (void)textViewDidEndEditing:(UITextView *)textView {
73 | self.post.body = self.bodyText.text;
74 | }
75 |
76 | #pragma mark - Actions
77 |
78 | - (IBAction)done:(UIBarButtonItem *)sender {
79 | self.post.title = self.titleField.text;
80 | self.post.body = self.bodyText.text;
81 | [self.postsViewController finishedEditing:self.post AndCancelled:NO];
82 | }
83 |
84 | - (IBAction)cancel:(UIBarButtonItem *)sender {
85 | [self.postsViewController finishedEditing:self.post AndCancelled:YES];
86 | }
87 |
88 |
89 | @end
90 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/app/controllers/posts_controller.rb:
--------------------------------------------------------------------------------
1 | class PostsController < ApplicationController
2 | # GET /posts
3 | # GET /posts.json
4 | def index
5 | if (params[:topic_id] && params[:topic_id] != '(null)')
6 | @posts = Post.find(:all, :conditions => ["topic_id = #{params[:topic_id]}"])
7 | else
8 | @posts = Post.all
9 | end
10 |
11 | respond_to do |format|
12 | format.html # index.html.erb
13 | format.json { render json: @posts }
14 | end
15 | end
16 |
17 | # GET /posts/1
18 | # GET /posts/1.json
19 | def show
20 | @post = Post.find(params[:id])
21 |
22 | respond_to do |format|
23 | format.html # show.html.erb
24 | format.json { render json: @post }
25 | end
26 | end
27 |
28 | # GET /posts/new
29 | # GET /posts/new.json
30 | def new
31 | @post = Post.new
32 |
33 | respond_to do |format|
34 | format.html # new.html.erb
35 | format.json { render json: @post }
36 | end
37 | end
38 |
39 | # GET /posts/1/edit
40 | def edit
41 | @post = Post.find(params[:id])
42 | end
43 |
44 | # POST /posts
45 | # POST /posts.json
46 | def create
47 | params[:post].delete(:id)
48 | @post = Post.new(params[:post])
49 | logger.info "new post #{@post.as_json}"
50 | logger.info "paramss #{params}"
51 | respond_to do |format|
52 | if @post.save
53 | format.html { redirect_to @post, notice: 'Post was successfully created.' }
54 | format.json { render json: @post, status: :created, location: @post }
55 | # output = render json: @post, status: :created, location: @post
56 | # format.json { output }
57 | # logger.info "gave-back #{output}"
58 | else
59 | format.html { render action: "new" }
60 | format.json { render json: @post.errors, status: :unprocessable_entity }
61 | end
62 | end
63 | end
64 |
65 | # PUT /posts/1
66 | # PUT /posts/1.json
67 | def update
68 | @post = Post.find(params[:id])
69 |
70 | respond_to do |format|
71 | if @post.update_attributes(params[:post])
72 | format.html { redirect_to @post, notice: 'Post was successfully updated.' }
73 | format.json { head :ok }
74 | else
75 | format.html { render action: "edit" }
76 | format.json { render json: @post.errors, status: :unprocessable_entity }
77 | end
78 | end
79 | end
80 |
81 | # DELETE /posts/1
82 | # DELETE /posts/1.json
83 | def destroy
84 | @post = Post.find(params[:id])
85 | @post.destroy
86 |
87 | respond_to do |format|
88 | format.html { redirect_to posts_url }
89 | format.json { head :ok }
90 | end
91 | end
92 | end
93 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/Generated/_Author.h:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This file is machine-generated and constantly overwritten.
2 | // Make changes to Author.h instead.
3 |
4 | #import
5 | #import "RootManagedObjectClass.h"
6 |
7 | extern const struct AuthorAttributes {
8 | __unsafe_unretained NSString *authorID;
9 | __unsafe_unretained NSString *email;
10 | __unsafe_unretained NSString *userName;
11 | } AuthorAttributes;
12 |
13 | extern const struct AuthorRelationships {
14 | __unsafe_unretained NSString *posts;
15 | } AuthorRelationships;
16 |
17 | extern const struct AuthorFetchedProperties {
18 | } AuthorFetchedProperties;
19 |
20 | @class Post;
21 |
22 |
23 |
24 |
25 |
26 | @interface AuthorID : NSManagedObjectID {}
27 | @end
28 |
29 | @interface _Author : RootManagedObjectClass {}
30 | + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_;
31 | + (NSString*)entityName;
32 | + (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_;
33 | - (AuthorID*)objectID;
34 |
35 |
36 |
37 |
38 | @property (nonatomic, strong) NSNumber *authorID;
39 |
40 |
41 | @property short authorIDValue;
42 | - (short)authorIDValue;
43 | - (void)setAuthorIDValue:(short)value_;
44 |
45 | //- (BOOL)validateAuthorID:(id*)value_ error:(NSError**)error_;
46 |
47 |
48 |
49 |
50 | @property (nonatomic, strong) NSString *email;
51 |
52 |
53 | //- (BOOL)validateEmail:(id*)value_ error:(NSError**)error_;
54 |
55 |
56 |
57 |
58 | @property (nonatomic, strong) NSString *userName;
59 |
60 |
61 | //- (BOOL)validateUserName:(id*)value_ error:(NSError**)error_;
62 |
63 |
64 |
65 |
66 |
67 | @property (nonatomic, strong) NSSet* posts;
68 |
69 | - (NSMutableSet*)postsSet;
70 |
71 |
72 |
73 |
74 | @end
75 |
76 | @interface _Author (CoreDataGeneratedAccessors)
77 |
78 | - (void)addPosts:(NSSet*)value_;
79 | - (void)removePosts:(NSSet*)value_;
80 | - (void)addPostsObject:(Post*)value_;
81 | - (void)removePostsObject:(Post*)value_;
82 |
83 | @end
84 |
85 | @interface _Author (CoreDataGeneratedPrimitiveAccessors)
86 |
87 |
88 | - (NSNumber*)primitiveAuthorID;
89 | - (void)setPrimitiveAuthorID:(NSNumber*)value;
90 |
91 | - (short)primitiveAuthorIDValue;
92 | - (void)setPrimitiveAuthorIDValue:(short)value_;
93 |
94 |
95 |
96 |
97 | - (NSString*)primitiveEmail;
98 | - (void)setPrimitiveEmail:(NSString*)value;
99 |
100 |
101 |
102 |
103 | - (NSString*)primitiveUserName;
104 | - (void)setPrimitiveUserName:(NSString*)value;
105 |
106 |
107 |
108 |
109 |
110 | - (NSMutableSet*)primitivePosts;
111 | - (void)setPrimitivePosts:(NSMutableSet*)value;
112 |
113 |
114 | @end
115 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/ldtrkpoc2.xcdatamodeld/ldtrkpoc2.xcdatamodel/contents:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/CoreDataTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // CoreDataTableViewController.h
3 | //
4 | // Created for Stanford CS193p Fall 2011.
5 | // Copyright 2011 Stanford University. All rights reserved.
6 | //
7 | // This class mostly just copies the code from NSFetchedResultsController's documentation page
8 | // into a subclass of UITableViewController.
9 | //
10 | // Just subclass this and set the fetchedResultsController.
11 | // The only UITableViewDataSource method you'll HAVE to implement is tableView:cellForRowAtIndexPath:.
12 | // And you can use the NSFetchedResultsController method objectAtIndexPath: to do it.
13 | //
14 | // Remember that once you create an NSFetchedResultsController, you CANNOT modify its @propertys.
15 | // If you want new fetch parameters (predicate, sorting, etc.),
16 | // create a NEW NSFetchedResultsController and set this class's fetchedResultsController @property again.
17 | //
18 |
19 | #import
20 | #import
21 |
22 | @interface CoreDataTableViewController : UITableViewController
23 |
24 | // The controller (this class fetches nothing if this is not set).
25 | @property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
26 |
27 | // Causes the fetchedResultsController to refetch the data.
28 | // You almost certainly never need to call this.
29 | // The NSFetchedResultsController class observes the context
30 | // (so if the objects in the context change, you do not need to call performFetch
31 | // since the NSFetchedResultsController will notice and update the table automatically).
32 | // This will also automatically be called if you change the fetchedResultsController @property.
33 | - (void)performFetch;
34 |
35 | // Turn this on before making any changes in the managed object context that
36 | // are a one-for-one result of the user manipulating rows directly in the table view.
37 | // Such changes cause the context to report them (after a brief delay),
38 | // and normally our fetchedResultsController would then try to update the table,
39 | // but that is unnecessary because the changes were made in the table already (by the user)
40 | // so the fetchedResultsController has nothing to do and needs to ignore those reports.
41 | // Turn this back off after the user has finished the change.
42 | // Note that the effect of setting this to NO actually gets delayed slightly
43 | // so as to ignore previously-posted, but not-yet-processed context-changed notifications,
44 | // therefore it is fine to set this to YES at the beginning of, e.g., tableView:moveRowAtIndexPath:toIndexPath:,
45 | // and then set it back to NO at the end of your implementation of that method.
46 | // It is not necessary (in fact, not desirable) to set this during row deletion or insertion
47 | // (but definitely for row moves).
48 | @property (nonatomic) BOOL suspendAutomaticTrackingOfChangesInManagedObjectContext;
49 |
50 | // Set to YES to get some debugging output in the console.
51 | @property BOOL debug;
52 |
53 | @end
54 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: http://rubygems.org/
3 | specs:
4 | actionmailer (3.1.1)
5 | actionpack (= 3.1.1)
6 | mail (~> 2.3.0)
7 | actionpack (3.1.1)
8 | activemodel (= 3.1.1)
9 | activesupport (= 3.1.1)
10 | builder (~> 3.0.0)
11 | erubis (~> 2.7.0)
12 | i18n (~> 0.6)
13 | rack (~> 1.3.2)
14 | rack-cache (~> 1.1)
15 | rack-mount (~> 0.8.2)
16 | rack-test (~> 0.6.1)
17 | sprockets (~> 2.0.2)
18 | activemodel (3.1.1)
19 | activesupport (= 3.1.1)
20 | builder (~> 3.0.0)
21 | i18n (~> 0.6)
22 | activerecord (3.1.1)
23 | activemodel (= 3.1.1)
24 | activesupport (= 3.1.1)
25 | arel (~> 2.2.1)
26 | tzinfo (~> 0.3.29)
27 | activeresource (3.1.1)
28 | activemodel (= 3.1.1)
29 | activesupport (= 3.1.1)
30 | activesupport (3.1.1)
31 | multi_json (~> 1.0)
32 | ansi (1.4.1)
33 | arel (2.2.1)
34 | builder (3.0.0)
35 | coffee-rails (3.1.1)
36 | coffee-script (>= 2.2.0)
37 | railties (~> 3.1.0)
38 | coffee-script (2.2.0)
39 | coffee-script-source
40 | execjs
41 | coffee-script-source (1.1.3)
42 | erubis (2.7.0)
43 | execjs (1.2.12)
44 | multi_json (~> 1.0)
45 | ffaker (1.12.1)
46 | hike (1.2.1)
47 | i18n (0.6.0)
48 | jquery-rails (1.0.19)
49 | railties (~> 3.0)
50 | thor (~> 0.14)
51 | json (1.6.3)
52 | mail (2.3.0)
53 | i18n (>= 0.4.0)
54 | mime-types (~> 1.16)
55 | treetop (~> 1.4.8)
56 | mime-types (1.17.2)
57 | minitest (2.9.1)
58 | multi_json (1.0.4)
59 | polyglot (0.3.3)
60 | rack (1.3.5)
61 | rack-cache (1.1)
62 | rack (>= 0.4)
63 | rack-mount (0.8.3)
64 | rack (>= 1.0.0)
65 | rack-ssl (1.3.2)
66 | rack
67 | rack-test (0.6.1)
68 | rack (>= 1.0)
69 | rails (3.1.1)
70 | actionmailer (= 3.1.1)
71 | actionpack (= 3.1.1)
72 | activerecord (= 3.1.1)
73 | activeresource (= 3.1.1)
74 | activesupport (= 3.1.1)
75 | bundler (~> 1.0)
76 | railties (= 3.1.1)
77 | railties (3.1.1)
78 | actionpack (= 3.1.1)
79 | activesupport (= 3.1.1)
80 | rack-ssl (~> 1.3.2)
81 | rake (>= 0.8.7)
82 | rdoc (~> 3.4)
83 | thor (~> 0.14.6)
84 | rake (0.9.2.2)
85 | random_data (1.5.2)
86 | rdoc (3.12)
87 | json (~> 1.4)
88 | sass (3.1.12)
89 | sass-rails (3.1.5)
90 | actionpack (~> 3.1.0)
91 | railties (~> 3.1.0)
92 | sass (~> 3.1.10)
93 | tilt (~> 1.3.2)
94 | sprockets (2.0.3)
95 | hike (~> 1.2)
96 | rack (~> 1.0)
97 | tilt (~> 1.1, != 1.3.0)
98 | sqlite3 (1.3.5)
99 | thor (0.14.6)
100 | tilt (1.3.3)
101 | treetop (1.4.10)
102 | polyglot
103 | polyglot (>= 0.3.1)
104 | turn (0.8.3)
105 | ansi
106 | tzinfo (0.3.31)
107 | uglifier (1.2.0)
108 | execjs (>= 0.3.0)
109 | multi_json (>= 1.0.2)
110 |
111 | PLATFORMS
112 | ruby
113 |
114 | DEPENDENCIES
115 | coffee-rails (~> 3.1.1)
116 | ffaker
117 | jquery-rails
118 | minitest
119 | rails (= 3.1.1)
120 | random_data
121 | sass-rails (~> 3.1.4)
122 | sqlite3
123 | turn
124 | uglifier (>= 1.0.3)
125 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Introduction
2 | =========================
3 |
4 | This project is a test-example-project for an iOS iPhone app that communicates with a Ruby on Rails based backend. It uses iOS5 SDK, Ruby 1.92, Rails 3.1 and RestKit.
5 |
6 | The goal was to create a super simple (small) iOS app that uses Storyboards and is able to pull and create objects with the website over JSON. All using RestKit and CoreData best practices.
7 |
8 | The datamodel is inspired by Pierre Martin's questions on the [RestKit Google Group](https://groups.google.com/group/restkit):
9 |
10 | [](http://dl.dropbox.com/u/212730/lottadot-restkit-ios-rails3-1-advanced_datamodel_diagram.png)
11 |
12 | Bascially it is:
13 |
14 | * topic has_many posts
15 | * post belongs_to a topic
16 | * post belongs_to an author
17 | * author has_many posts
18 |
19 | I used Restkit HEAD.
20 |
21 | Installation
22 | =========================
23 |
24 | Quick Start (aka TL;DR)
25 | -----------
26 |
27 | (clone the repo):
28 |
29 | ```console
30 | cd lottadot-restkit-ios-rails3-1-advanced
31 | ```console
32 |
33 | (update the git submodule that points to Restkit):
34 |
35 | ```console
36 | git submodule update --init --recursive
37 | ```console
38 |
39 | (start the rails app in a terminal window):
40 |
41 | ```console
42 | cd ldtrkpoc2svr
43 | ```console
44 |
45 | (if you use RVM:)
46 | ```console
47 | rvm use ruby-1.9.2-p290@ldtrkpoc2svr
48 | ```console
49 |
50 | (If you see something like 'report_activate_error' you'll have to do 'gem install rails'. If you see something about gemset doesn't exist, then follow rvm's instructions to install the new gemset (ie rvm --create use ruby-1.9.2-p290@ldtrkpoc2svr ), and don't forget to 'gem install rails' when it's finished.)
51 |
52 | ```console
53 | bundle install
54 | rake db:migrate
55 | rake db:seed
56 | rails s
57 | ```console
58 |
59 | Open a web browser and open [http://lvh.me:3000/](http://lvh.me:3000/)
60 |
61 | Try it out
62 | =========================
63 | open the xcode project.
64 | run it.
65 |
66 | You should see
67 |
68 | [](http://dl.dropbox.com/u/212730/lottadot-restkit-ios-rails3-1-advanced_screenshot.png)
69 |
70 | If you press the 'add one' button it should contact the website, create a new Topic on the website. After creating it should update the UITableView so you see the new Topic.
71 |
72 | ---
73 | ###Optional
74 |
75 | If you'd like to "load test", you can generate random-topic-data (default is 150 records) Run:
76 |
77 | ```console
78 | rake myapp:load:random_topics
79 | ```console
80 |
81 | ---
82 | ###TODO
83 |
84 | * iOS: add code to let you cancel an attempt to add a new Topic
85 | * iOS: re-do the TopicEditor and decouple it.
86 | * iOS: add code to let you edit/delete a topic (which would cascade to delete it's posts)
87 | * iOS: add code to let you create/edit/delete a new post
88 | * website: Login/out of the website (maybe with Devise in the RoR app)
89 | * iOS: force the user to authenticate, then when creating posts associate the user/"author" with it.
90 |
91 | Contributing
92 | -------------------------
93 |
94 | Forks, patches and other feedback are always welcome. Please for it and submit a pull request.
95 |
96 | Credits
97 | -------------------------
98 |
99 | * RestKit is brought to you by [Blake Watters](http://twitter.com/blakewatters) and the RestKit team.
100 | * CoreDataTableViewController is brought to you by [Stanford CS193p Fall 2011](http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=480479762)
101 |
102 |
103 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/Generated/_Post.h:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This file is machine-generated and constantly overwritten.
2 | // Make changes to Post.h instead.
3 |
4 | #import
5 | #import "RootManagedObjectClass.h"
6 |
7 | extern const struct PostAttributes {
8 | __unsafe_unretained NSString *authorID;
9 | __unsafe_unretained NSString *body;
10 | __unsafe_unretained NSString *postID;
11 | __unsafe_unretained NSString *title;
12 | __unsafe_unretained NSString *topicID;
13 | } PostAttributes;
14 |
15 | extern const struct PostRelationships {
16 | __unsafe_unretained NSString *author;
17 | __unsafe_unretained NSString *topic;
18 | } PostRelationships;
19 |
20 | extern const struct PostFetchedProperties {
21 | } PostFetchedProperties;
22 |
23 | @class Author;
24 | @class Topic;
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | @interface PostID : NSManagedObjectID {}
33 | @end
34 |
35 | @interface _Post : RootManagedObjectClass {}
36 | + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_;
37 | + (NSString*)entityName;
38 | + (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_;
39 | - (PostID*)objectID;
40 |
41 |
42 |
43 |
44 | @property (nonatomic, strong) NSNumber *authorID;
45 |
46 |
47 | @property short authorIDValue;
48 | - (short)authorIDValue;
49 | - (void)setAuthorIDValue:(short)value_;
50 |
51 | //- (BOOL)validateAuthorID:(id*)value_ error:(NSError**)error_;
52 |
53 |
54 |
55 |
56 | @property (nonatomic, strong) NSString *body;
57 |
58 |
59 | //- (BOOL)validateBody:(id*)value_ error:(NSError**)error_;
60 |
61 |
62 |
63 |
64 | @property (nonatomic, strong) NSNumber *postID;
65 |
66 |
67 | @property short postIDValue;
68 | - (short)postIDValue;
69 | - (void)setPostIDValue:(short)value_;
70 |
71 | //- (BOOL)validatePostID:(id*)value_ error:(NSError**)error_;
72 |
73 |
74 |
75 |
76 | @property (nonatomic, strong) NSString *title;
77 |
78 |
79 | //- (BOOL)validateTitle:(id*)value_ error:(NSError**)error_;
80 |
81 |
82 |
83 |
84 | @property (nonatomic, strong) NSNumber *topicID;
85 |
86 |
87 | @property short topicIDValue;
88 | - (short)topicIDValue;
89 | - (void)setTopicIDValue:(short)value_;
90 |
91 | //- (BOOL)validateTopicID:(id*)value_ error:(NSError**)error_;
92 |
93 |
94 |
95 |
96 |
97 | @property (nonatomic, strong) Author* author;
98 |
99 | //- (BOOL)validateAuthor:(id*)value_ error:(NSError**)error_;
100 |
101 |
102 |
103 |
104 | @property (nonatomic, strong) Topic* topic;
105 |
106 | //- (BOOL)validateTopic:(id*)value_ error:(NSError**)error_;
107 |
108 |
109 |
110 |
111 | @end
112 |
113 | @interface _Post (CoreDataGeneratedAccessors)
114 |
115 | @end
116 |
117 | @interface _Post (CoreDataGeneratedPrimitiveAccessors)
118 |
119 |
120 | - (NSNumber*)primitiveAuthorID;
121 | - (void)setPrimitiveAuthorID:(NSNumber*)value;
122 |
123 | - (short)primitiveAuthorIDValue;
124 | - (void)setPrimitiveAuthorIDValue:(short)value_;
125 |
126 |
127 |
128 |
129 | - (NSString*)primitiveBody;
130 | - (void)setPrimitiveBody:(NSString*)value;
131 |
132 |
133 |
134 |
135 | - (NSNumber*)primitivePostID;
136 | - (void)setPrimitivePostID:(NSNumber*)value;
137 |
138 | - (short)primitivePostIDValue;
139 | - (void)setPrimitivePostIDValue:(short)value_;
140 |
141 |
142 |
143 |
144 | - (NSString*)primitiveTitle;
145 | - (void)setPrimitiveTitle:(NSString*)value;
146 |
147 |
148 |
149 |
150 | - (NSNumber*)primitiveTopicID;
151 | - (void)setPrimitiveTopicID:(NSNumber*)value;
152 |
153 | - (short)primitiveTopicIDValue;
154 | - (void)setPrimitiveTopicIDValue:(short)value_;
155 |
156 |
157 |
158 |
159 |
160 | - (Author*)primitiveAuthor;
161 | - (void)setPrimitiveAuthor:(Author*)value;
162 |
163 |
164 |
165 | - (Topic*)primitiveTopic;
166 | - (void)setPrimitiveTopic:(Topic*)value;
167 |
168 |
169 | @end
170 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2.xcodeproj/xcuserdata/shane.xcuserdatad/xcschemes/ldtrkpoc2.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
14 |
20 |
21 |
22 |
23 |
24 |
29 |
30 |
32 |
38 |
39 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
59 |
60 |
66 |
67 |
68 |
69 |
70 |
71 |
77 |
78 |
84 |
85 |
86 |
87 |
89 |
90 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/Generated/_Post.m:
--------------------------------------------------------------------------------
1 | // DO NOT EDIT. This file is machine-generated and constantly overwritten.
2 | // Make changes to Post.m instead.
3 |
4 | #import "_Post.h"
5 |
6 | const struct PostAttributes PostAttributes = {
7 | .authorID = @"authorID",
8 | .body = @"body",
9 | .postID = @"postID",
10 | .title = @"title",
11 | .topicID = @"topicID",
12 | };
13 |
14 | const struct PostRelationships PostRelationships = {
15 | .author = @"author",
16 | .topic = @"topic",
17 | };
18 |
19 | const struct PostFetchedProperties PostFetchedProperties = {
20 | };
21 |
22 | @implementation PostID
23 | @end
24 |
25 | @implementation _Post
26 |
27 | + (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ {
28 | NSParameterAssert(moc_);
29 | return [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:moc_];
30 | }
31 |
32 | + (NSString*)entityName {
33 | return @"Post";
34 | }
35 |
36 | + (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_ {
37 | NSParameterAssert(moc_);
38 | return [NSEntityDescription entityForName:@"Post" inManagedObjectContext:moc_];
39 | }
40 |
41 | - (PostID*)objectID {
42 | return (PostID*)[super objectID];
43 | }
44 |
45 | + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
46 | NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
47 |
48 | if ([key isEqualToString:@"authorIDValue"]) {
49 | NSSet *affectingKey = [NSSet setWithObject:@"authorID"];
50 | keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey];
51 | }
52 | if ([key isEqualToString:@"postIDValue"]) {
53 | NSSet *affectingKey = [NSSet setWithObject:@"postID"];
54 | keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey];
55 | }
56 | if ([key isEqualToString:@"topicIDValue"]) {
57 | NSSet *affectingKey = [NSSet setWithObject:@"topicID"];
58 | keyPaths = [keyPaths setByAddingObjectsFromSet:affectingKey];
59 | }
60 |
61 | return keyPaths;
62 | }
63 |
64 |
65 |
66 |
67 | @dynamic authorID;
68 |
69 |
70 |
71 | - (short)authorIDValue {
72 | NSNumber *result = [self authorID];
73 | return [result shortValue];
74 | }
75 |
76 | - (void)setAuthorIDValue:(short)value_ {
77 | [self setAuthorID:[NSNumber numberWithShort:value_]];
78 | }
79 |
80 | - (short)primitiveAuthorIDValue {
81 | NSNumber *result = [self primitiveAuthorID];
82 | return [result shortValue];
83 | }
84 |
85 | - (void)setPrimitiveAuthorIDValue:(short)value_ {
86 | [self setPrimitiveAuthorID:[NSNumber numberWithShort:value_]];
87 | }
88 |
89 |
90 |
91 |
92 |
93 | @dynamic body;
94 |
95 |
96 |
97 |
98 |
99 |
100 | @dynamic postID;
101 |
102 |
103 |
104 | - (short)postIDValue {
105 | NSNumber *result = [self postID];
106 | return [result shortValue];
107 | }
108 |
109 | - (void)setPostIDValue:(short)value_ {
110 | [self setPostID:[NSNumber numberWithShort:value_]];
111 | }
112 |
113 | - (short)primitivePostIDValue {
114 | NSNumber *result = [self primitivePostID];
115 | return [result shortValue];
116 | }
117 |
118 | - (void)setPrimitivePostIDValue:(short)value_ {
119 | [self setPrimitivePostID:[NSNumber numberWithShort:value_]];
120 | }
121 |
122 |
123 |
124 |
125 |
126 | @dynamic title;
127 |
128 |
129 |
130 |
131 |
132 |
133 | @dynamic topicID;
134 |
135 |
136 |
137 | - (short)topicIDValue {
138 | NSNumber *result = [self topicID];
139 | return [result shortValue];
140 | }
141 |
142 | - (void)setTopicIDValue:(short)value_ {
143 | [self setTopicID:[NSNumber numberWithShort:value_]];
144 | }
145 |
146 | - (short)primitiveTopicIDValue {
147 | NSNumber *result = [self primitiveTopicID];
148 | return [result shortValue];
149 | }
150 |
151 | - (void)setPrimitiveTopicIDValue:(short)value_ {
152 | [self setPrimitiveTopicID:[NSNumber numberWithShort:value_]];
153 | }
154 |
155 |
156 |
157 |
158 |
159 | @dynamic author;
160 |
161 |
162 |
163 | @dynamic topic;
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | @end
172 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/PostsTableViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1280
5 | 11C25
6 | 1919
7 | 1138.11
8 | 566.00
9 |
10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
11 | 916
12 |
13 |
14 | IBProxyObject
15 | IBUIView
16 |
17 |
18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
19 |
20 |
21 | PluginDependencyRecalculationVersion
22 |
23 |
24 |
25 |
26 | IBFilesOwner
27 | IBCocoaTouchFramework
28 |
29 |
30 | IBFirstResponder
31 | IBCocoaTouchFramework
32 |
33 |
34 |
35 | 274
36 | {{0, 20}, {320, 460}}
37 |
38 |
39 |
40 | 3
41 | MQA
42 |
43 | 2
44 |
45 |
46 |
47 | IBCocoaTouchFramework
48 |
49 |
50 |
51 |
52 |
53 |
54 | view
55 |
56 |
57 |
58 | 3
59 |
60 |
61 |
62 |
63 |
64 | 0
65 |
66 |
67 |
68 |
69 |
70 | 1
71 |
72 |
73 |
74 |
75 | -1
76 |
77 |
78 | File's Owner
79 |
80 |
81 | -2
82 |
83 |
84 |
85 |
86 |
87 |
88 | PostsTableViewController
89 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
90 | UIResponder
91 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
92 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
93 |
94 |
95 |
96 |
97 |
98 | 3
99 |
100 |
101 |
102 |
103 | PostsTableViewController
104 | UIViewController
105 |
106 | IBProjectSource
107 | ./Classes/PostsTableViewController.h
108 |
109 |
110 |
111 |
112 | 0
113 | IBCocoaTouchFramework
114 | YES
115 | 3
116 | 916
117 |
118 |
119 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/CoreDataTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // CoreDataTableViewController.m
3 | //
4 | // Created for Stanford CS193p Fall 2011.
5 | // Copyright 2011 Stanford University. All rights reserved.
6 | //
7 |
8 | #import "CoreDataTableViewController.h"
9 |
10 | @interface CoreDataTableViewController()
11 | @property (nonatomic) BOOL beganUpdates;
12 | @end
13 |
14 | @implementation CoreDataTableViewController
15 |
16 | #pragma mark - Properties
17 |
18 | @synthesize fetchedResultsController = _fetchedResultsController;
19 | @synthesize suspendAutomaticTrackingOfChangesInManagedObjectContext = _suspendAutomaticTrackingOfChangesInManagedObjectContext;
20 | @synthesize debug = _debug;
21 | @synthesize beganUpdates = _beganUpdates;
22 |
23 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
24 | {
25 | return YES;
26 | }
27 |
28 | #pragma mark - Fetching
29 |
30 | - (void)performFetch
31 | {
32 | if (self.fetchedResultsController) {
33 | if (self.fetchedResultsController.fetchRequest.predicate) {
34 | if (self.debug) NSLog(@"[%@ %@] fetching %@ with predicate: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate);
35 | } else {
36 | if (self.debug) NSLog(@"[%@ %@] fetching all %@ (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName);
37 | }
38 | NSError *error;
39 | [self.fetchedResultsController performFetch:&error];
40 | if (error) NSLog(@"[%@ %@] %@ (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]);
41 | } else {
42 | if (self.debug) NSLog(@"[%@ %@] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
43 | }
44 | [self.tableView reloadData];
45 | }
46 |
47 | - (void)setFetchedResultsController:(NSFetchedResultsController *)newfrc
48 | {
49 | NSFetchedResultsController *oldfrc = _fetchedResultsController;
50 | if (newfrc != oldfrc) {
51 | _fetchedResultsController = newfrc;
52 | newfrc.delegate = self;
53 | if ((!self.title || [self.title isEqualToString:oldfrc.fetchRequest.entity.name]) && (!self.navigationController || !self.navigationItem.title)) {
54 | self.title = newfrc.fetchRequest.entity.name;
55 | }
56 | if (newfrc) {
57 | if (self.debug) NSLog(@"[%@ %@] %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), oldfrc ? @"updated" : @"set");
58 | [self performFetch];
59 | } else {
60 | if (self.debug) NSLog(@"[%@ %@] reset to nil", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
61 | [self.tableView reloadData];
62 | }
63 | }
64 | }
65 |
66 | #pragma mark - UITableViewDataSource
67 |
68 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
69 | {
70 | return [[self.fetchedResultsController sections] count];
71 | }
72 |
73 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
74 | {
75 | return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
76 | }
77 |
78 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
79 | {
80 | return [[[self.fetchedResultsController sections] objectAtIndex:section] name];
81 | }
82 |
83 | - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
84 | {
85 | return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
86 | }
87 |
88 | - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
89 | {
90 | return [self.fetchedResultsController sectionIndexTitles];
91 | }
92 |
93 | #pragma mark - NSFetchedResultsControllerDelegate
94 |
95 | - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
96 | {
97 | if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) {
98 | [self.tableView beginUpdates];
99 | self.beganUpdates = YES;
100 | }
101 | }
102 |
103 | - (void)controller:(NSFetchedResultsController *)controller
104 | didChangeSection:(id )sectionInfo
105 | atIndex:(NSUInteger)sectionIndex
106 | forChangeType:(NSFetchedResultsChangeType)type
107 | {
108 | if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
109 | {
110 | switch(type)
111 | {
112 | case NSFetchedResultsChangeInsert:
113 | [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
114 | break;
115 |
116 | case NSFetchedResultsChangeDelete:
117 | [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
118 | break;
119 | }
120 | }
121 | }
122 |
123 |
124 | - (void)controller:(NSFetchedResultsController *)controller
125 | didChangeObject:(id)anObject
126 | atIndexPath:(NSIndexPath *)indexPath
127 | forChangeType:(NSFetchedResultsChangeType)type
128 | newIndexPath:(NSIndexPath *)newIndexPath
129 | {
130 | if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
131 | {
132 | switch(type)
133 | {
134 | case NSFetchedResultsChangeInsert:
135 | [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
136 | break;
137 |
138 | case NSFetchedResultsChangeDelete:
139 | [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
140 | break;
141 |
142 | case NSFetchedResultsChangeUpdate:
143 | [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
144 | break;
145 |
146 | case NSFetchedResultsChangeMove:
147 | [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
148 | [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
149 | break;
150 | }
151 | }
152 | }
153 |
154 | - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
155 | {
156 | if (self.beganUpdates) [self.tableView endUpdates];
157 | }
158 |
159 | - (void)endSuspensionOfUpdatesDueToContextChanges
160 | {
161 | _suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;
162 | }
163 |
164 | - (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend
165 | {
166 | if (suspend) {
167 | _suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
168 | } else {
169 | [self performSelector:@selector(endSuspensionOfUpdatesDueToContextChanges) withObject:0 afterDelay:0];
170 | }
171 | }
172 |
173 | @end
174 |
175 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/AuthorsTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // AuthorsTableViewController.m
3 | // ldtrkpoc2
4 | //
5 | // Created by Shane Zatezalo on 12/13/11.
6 | // Copyright (c) 2011 Lottadot LLC. All rights reserved.
7 | //
8 |
9 | #import "AuthorsTableViewController.h"
10 |
11 | #import "AuthorsTableViewController.h"
12 | #import
13 | #import "CoreDataTableViewController.h"
14 | #import "MyModelEntities.h"
15 | #import
16 |
17 | @interface AuthorsTableViewController ()
18 | - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
19 | - (void)setupPostsFetchedResultsController;
20 | - (void)fetchPostsDataFromRemote;
21 | @end
22 |
23 | @implementation AuthorsTableViewController
24 |
25 | @synthesize post = _post;
26 |
27 | - (void)didReceiveMemoryWarning
28 | {
29 | [super didReceiveMemoryWarning];
30 | // Release any cached data, images, etc that aren't in use.
31 | }
32 |
33 | #pragma mark - View lifecycle
34 |
35 | - (void)viewDidLoad
36 | {
37 | [super viewDidLoad];
38 | [[RKClient sharedClient].requestQueue cancelRequestsWithDelegate:self];
39 | }
40 |
41 | - (void)viewDidUnload
42 | {
43 | [super viewDidUnload];
44 | // Release any retained subviews of the main view.
45 | // e.g. self.myOutlet = nil;
46 | }
47 |
48 | - (void)viewWillAppear:(BOOL)animated {
49 | [super viewWillAppear:animated];
50 |
51 | if (nil == self.fetchedResultsController) {
52 | [self setupPostsFetchedResultsController];
53 |
54 | }
55 | self.debug = YES;
56 | //[self performFetch];
57 | NSLog(@"count:%i",[[self.fetchedResultsController sections] count]);
58 | //[self.tableView reloadData];
59 | [self fetchPostsDataFromRemote];
60 | }
61 |
62 | - (void)viewDidAppear:(BOOL)animated
63 | {
64 | [super viewDidAppear:animated];
65 | }
66 |
67 | - (void)viewWillDisappear:(BOOL)animated
68 | {
69 | [super viewWillDisappear:animated];
70 | }
71 |
72 | - (void)viewDidDisappear:(BOOL)animated
73 | {
74 | [super viewDidDisappear:animated];
75 | }
76 |
77 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
78 | {
79 | // Return YES for supported orientations
80 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
81 | }
82 |
83 | #pragma mark -
84 | #pragma mark Table view methods
85 |
86 |
87 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
88 |
89 | static NSString *reuseIdentifier = @"Author Cell";
90 |
91 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
92 | if (nil == cell) {
93 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
94 | }
95 | [self configureCell:cell atIndexPath:indexPath];
96 | return cell;
97 | }
98 |
99 | #pragma mark - Table Cell
100 |
101 | - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
102 | Author *author = [self.fetchedResultsController objectAtIndexPath:indexPath];
103 | cell.textLabel.text = [author userName];
104 | cell.detailTextLabel.text = [author email];
105 | }
106 |
107 |
108 | #pragma mark -
109 | #pragma mark Fetched results controller
110 |
111 | - (void)setupPostsFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
112 | {
113 | if (nil == self.fetchedResultsController) {
114 | //NSManagedObjectContext *managedObjectContext = [ApplicationDelegate managedObjectContext];
115 |
116 |
117 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Author"];
118 | request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"userName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]];
119 | // a predicate because we want ALL the Posts that belong to the topic
120 | //request.predicate = [NSPredicate predicateWithFormat:@"post.topicID = %@", self.topic.topicID];
121 | request.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"authorID = %i",[self.post.authorID intValue]]];
122 | self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
123 | managedObjectContext:self.post.managedObjectContext
124 | sectionNameKeyPath:nil
125 | cacheName:nil];
126 |
127 |
128 | }
129 | }
130 |
131 | - (void)fetchPostsDataFromRemote {
132 | // Load the object model via RestKit
133 | RKObjectManager* objectManager = [RKObjectManager sharedManager];
134 | NSString *url = [NSString stringWithFormat:@"/authors"];
135 | [objectManager loadObjectsAtResourcePath:url delegate:self
136 | block:^(RKObjectLoader* loader) {
137 | // The backend returns posts as a naked array in JSON, so we instruct the loader
138 | // to user the appropriate object mapping
139 | loader.objectMapping = [objectManager.mappingProvider objectMappingForClass:[Author class]];
140 | }];
141 | }
142 |
143 | #pragma mark RKObjectLoaderDelegate methods
144 |
145 | - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
146 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"LastUpdatedAt"];
147 | [[NSUserDefaults standardUserDefaults] synchronize];
148 | NSLog(@"Loaded authors: %@", objects);
149 | //[self loadObjectsFromDataStore];
150 | [self performFetch];
151 | //[self.tableView reloadData];
152 | }
153 |
154 | - (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
155 | UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Error"
156 | message:[error localizedDescription]
157 | delegate:nil
158 | cancelButtonTitle:@"OK" otherButtonTitles:nil];
159 |
160 | [alert show];
161 | NSLog(@"Hit error: %@", error);
162 | }
163 |
164 | #pragma mark topic
165 |
166 | - (void)setPost:(Post *)post {
167 | _post = post;
168 | self.title = post.author.userName;
169 | [self setupPostsFetchedResultsController];
170 | }
171 |
172 |
173 | #pragma mark Segue
174 |
175 | // Support segueing from this table to any view controller that has a Post @property.
176 |
177 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
178 | NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
179 | Post *clicked = [self.fetchedResultsController objectAtIndexPath:indexPath];
180 | // be somewhat generic here (slightly advanced usage)
181 | // we'll segue to ANY view controller that has a photographer @property
182 | if ([segue.destinationViewController respondsToSelector:@selector(setPost:)]) {
183 | // use performSelector:withObject: to send without compiler checking
184 | // (which is acceptable here because we used introspection to be sure this is okay)
185 | [segue.destinationViewController performSelector:@selector(setPost:) withObject:clicked];
186 | }
187 | }
188 |
189 | @end
--------------------------------------------------------------------------------
/iOS/core_data_empty/cdstuff/cdstuff/LDTAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // LDTAppDelegate.m
3 | // cdstuff
4 | //
5 | // Created by Shane Zatezalo on 12/8/11.
6 | // Copyright (c) 2011 Personal. All rights reserved.
7 | //
8 |
9 | #import "LDTAppDelegate.h"
10 |
11 | @implementation LDTAppDelegate
12 |
13 | @synthesize window = _window;
14 | @synthesize managedObjectContext = __managedObjectContext;
15 | @synthesize managedObjectModel = __managedObjectModel;
16 | @synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
19 | {
20 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
21 | // Override point for customization after application launch.
22 | self.window.backgroundColor = [UIColor whiteColor];
23 | [self.window makeKeyAndVisible];
24 | return YES;
25 | }
26 |
27 | - (void)applicationWillResignActive:(UIApplication *)application
28 | {
29 | /*
30 | Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
31 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
32 | */
33 | }
34 |
35 | - (void)applicationDidEnterBackground:(UIApplication *)application
36 | {
37 | /*
38 | Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
39 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
40 | */
41 | }
42 |
43 | - (void)applicationWillEnterForeground:(UIApplication *)application
44 | {
45 | /*
46 | Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
47 | */
48 | }
49 |
50 | - (void)applicationDidBecomeActive:(UIApplication *)application
51 | {
52 | /*
53 | Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
54 | */
55 | }
56 |
57 | - (void)applicationWillTerminate:(UIApplication *)application
58 | {
59 | // Saves changes in the application's managed object context before the application terminates.
60 | [self saveContext];
61 | }
62 |
63 | - (void)saveContext
64 | {
65 | NSError *error = nil;
66 | NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
67 | if (managedObjectContext != nil)
68 | {
69 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
70 | {
71 | /*
72 | Replace this implementation with code to handle the error appropriately.
73 |
74 | abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
75 | */
76 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
77 | abort();
78 | }
79 | }
80 | }
81 |
82 | #pragma mark - Core Data stack
83 |
84 | /**
85 | Returns the managed object context for the application.
86 | If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
87 | */
88 | - (NSManagedObjectContext *)managedObjectContext
89 | {
90 | if (__managedObjectContext != nil)
91 | {
92 | return __managedObjectContext;
93 | }
94 |
95 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
96 | if (coordinator != nil)
97 | {
98 | __managedObjectContext = [[NSManagedObjectContext alloc] init];
99 | [__managedObjectContext setPersistentStoreCoordinator:coordinator];
100 | }
101 | return __managedObjectContext;
102 | }
103 |
104 | /**
105 | Returns the managed object model for the application.
106 | If the model doesn't already exist, it is created from the application's model.
107 | */
108 | - (NSManagedObjectModel *)managedObjectModel
109 | {
110 | if (__managedObjectModel != nil)
111 | {
112 | return __managedObjectModel;
113 | }
114 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"cdstuff" withExtension:@"momd"];
115 | __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
116 | return __managedObjectModel;
117 | }
118 |
119 | /**
120 | Returns the persistent store coordinator for the application.
121 | If the coordinator doesn't already exist, it is created and the application's store added to it.
122 | */
123 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
124 | {
125 | if (__persistentStoreCoordinator != nil)
126 | {
127 | return __persistentStoreCoordinator;
128 | }
129 |
130 | NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"cdstuff.sqlite"];
131 |
132 | NSError *error = nil;
133 | __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
134 | if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
135 | {
136 | /*
137 | Replace this implementation with code to handle the error appropriately.
138 |
139 | abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
140 |
141 | Typical reasons for an error here include:
142 | * The persistent store is not accessible;
143 | * The schema for the persistent store is incompatible with current managed object model.
144 | Check the error message to determine what the actual problem was.
145 |
146 |
147 | If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
148 |
149 | If you encounter schema incompatibility errors during development, you can reduce their frequency by:
150 | * Simply deleting the existing store:
151 | [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
152 |
153 | * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
154 | [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
155 |
156 | Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
157 |
158 | */
159 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
160 | abort();
161 | }
162 |
163 | return __persistentStoreCoordinator;
164 | }
165 |
166 | #pragma mark - Application's Documents directory
167 |
168 | /**
169 | Returns the URL to the application's Documents directory.
170 | */
171 | - (NSURL *)applicationDocumentsDirectory
172 | {
173 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
174 | }
175 |
176 | @end
177 |
--------------------------------------------------------------------------------
/ldtrkpoc2svr/README:
--------------------------------------------------------------------------------
1 | == Welcome to Rails
2 |
3 | Rails is a web-application framework that includes everything needed to create
4 | database-backed web applications according to the Model-View-Control pattern.
5 |
6 | This pattern splits the view (also called the presentation) into "dumb"
7 | templates that are primarily responsible for inserting pre-built data in between
8 | HTML tags. The model contains the "smart" domain objects (such as Account,
9 | Product, Person, Post) that holds all the business logic and knows how to
10 | persist themselves to a database. The controller handles the incoming requests
11 | (such as Save New Account, Update Product, Show Post) by manipulating the model
12 | and directing data to the view.
13 |
14 | In Rails, the model is handled by what's called an object-relational mapping
15 | layer entitled Active Record. This layer allows you to present the data from
16 | database rows as objects and embellish these data objects with business logic
17 | methods. You can read more about Active Record in
18 | link:files/vendor/rails/activerecord/README.html.
19 |
20 | The controller and view are handled by the Action Pack, which handles both
21 | layers by its two parts: Action View and Action Controller. These two layers
22 | are bundled in a single package due to their heavy interdependence. This is
23 | unlike the relationship between the Active Record and Action Pack that is much
24 | more separate. Each of these packages can be used independently outside of
25 | Rails. You can read more about Action Pack in
26 | link:files/vendor/rails/actionpack/README.html.
27 |
28 |
29 | == Getting Started
30 |
31 | 1. At the command prompt, create a new Rails application:
32 | rails new myapp (where myapp is the application name)
33 |
34 | 2. Change directory to myapp and start the web server:
35 | cd myapp; rails server (run with --help for options)
36 |
37 | 3. Go to http://localhost:3000/ and you'll see:
38 | "Welcome aboard: You're riding Ruby on Rails!"
39 |
40 | 4. Follow the guidelines to start developing your application. You can find
41 | the following resources handy:
42 |
43 | * The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
44 | * Ruby on Rails Tutorial Book: http://www.railstutorial.org/
45 |
46 |
47 | == Debugging Rails
48 |
49 | Sometimes your application goes wrong. Fortunately there are a lot of tools that
50 | will help you debug it and get it back on the rails.
51 |
52 | First area to check is the application log files. Have "tail -f" commands
53 | running on the server.log and development.log. Rails will automatically display
54 | debugging and runtime information to these files. Debugging info will also be
55 | shown in the browser on requests from 127.0.0.1.
56 |
57 | You can also log your own messages directly into the log file from your code
58 | using the Ruby logger class from inside your controllers. Example:
59 |
60 | class WeblogController < ActionController::Base
61 | def destroy
62 | @weblog = Weblog.find(params[:id])
63 | @weblog.destroy
64 | logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
65 | end
66 | end
67 |
68 | The result will be a message in your log file along the lines of:
69 |
70 | Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
71 |
72 | More information on how to use the logger is at http://www.ruby-doc.org/core/
73 |
74 | Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
75 | several books available online as well:
76 |
77 | * Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
78 | * Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
79 |
80 | These two books will bring you up to speed on the Ruby language and also on
81 | programming in general.
82 |
83 |
84 | == Debugger
85 |
86 | Debugger support is available through the debugger command when you start your
87 | Mongrel or WEBrick server with --debugger. This means that you can break out of
88 | execution at any point in the code, investigate and change the model, and then,
89 | resume execution! You need to install ruby-debug to run the server in debugging
90 | mode. With gems, use sudo gem install ruby-debug . Example:
91 |
92 | class WeblogController < ActionController::Base
93 | def index
94 | @posts = Post.all
95 | debugger
96 | end
97 | end
98 |
99 | So the controller will accept the action, run the first line, then present you
100 | with a IRB prompt in the server window. Here you can do things like:
101 |
102 | >> @posts.inspect
103 | => "[#nil, "body"=>nil, "id"=>"1"}>,
105 | #"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
107 | >> @posts.first.title = "hello from a debugger"
108 | => "hello from a debugger"
109 |
110 | ...and even better, you can examine how your runtime objects actually work:
111 |
112 | >> f = @posts.first
113 | => #nil, "body"=>nil, "id"=>"1"}>
114 | >> f.
115 | Display all 152 possibilities? (y or n)
116 |
117 | Finally, when you're ready to resume execution, you can enter "cont".
118 |
119 |
120 | == Console
121 |
122 | The console is a Ruby shell, which allows you to interact with your
123 | application's domain model. Here you'll have all parts of the application
124 | configured, just like it is when the application is running. You can inspect
125 | domain models, change values, and save to the database. Starting the script
126 | without arguments will launch it in the development environment.
127 |
128 | To start the console, run rails console from the application
129 | directory.
130 |
131 | Options:
132 |
133 | * Passing the -s, --sandbox argument will rollback any modifications
134 | made to the database.
135 | * Passing an environment name as an argument will load the corresponding
136 | environment. Example: rails console production .
137 |
138 | To reload your controllers and models after launching the console run
139 | reload!
140 |
141 | More information about irb can be found at:
142 | link:http://www.rubycentral.org/pickaxe/irb.html
143 |
144 |
145 | == dbconsole
146 |
147 | You can go to the command line of your database directly through rails
148 | dbconsole . You would be connected to the database with the credentials
149 | defined in database.yml. Starting the script without arguments will connect you
150 | to the development database. Passing an argument will connect you to a different
151 | database, like rails dbconsole production . Currently works for MySQL,
152 | PostgreSQL and SQLite 3.
153 |
154 | == Description of Contents
155 |
156 | The default directory structure of a generated Ruby on Rails application:
157 |
158 | |-- app
159 | | |-- assets
160 | | |-- images
161 | | |-- javascripts
162 | | `-- stylesheets
163 | | |-- controllers
164 | | |-- helpers
165 | | |-- mailers
166 | | |-- models
167 | | `-- views
168 | | `-- layouts
169 | |-- config
170 | | |-- environments
171 | | |-- initializers
172 | | `-- locales
173 | |-- db
174 | |-- doc
175 | |-- lib
176 | | `-- tasks
177 | |-- log
178 | |-- public
179 | |-- script
180 | |-- test
181 | | |-- fixtures
182 | | |-- functional
183 | | |-- integration
184 | | |-- performance
185 | | `-- unit
186 | |-- tmp
187 | | |-- cache
188 | | |-- pids
189 | | |-- sessions
190 | | `-- sockets
191 | `-- vendor
192 | |-- assets
193 | `-- stylesheets
194 | `-- plugins
195 |
196 | app
197 | Holds all the code that's specific to this particular application.
198 |
199 | app/assets
200 | Contains subdirectories for images, stylesheets, and JavaScript files.
201 |
202 | app/controllers
203 | Holds controllers that should be named like weblogs_controller.rb for
204 | automated URL mapping. All controllers should descend from
205 | ApplicationController which itself descends from ActionController::Base.
206 |
207 | app/models
208 | Holds models that should be named like post.rb. Models descend from
209 | ActiveRecord::Base by default.
210 |
211 | app/views
212 | Holds the template files for the view that should be named like
213 | weblogs/index.html.erb for the WeblogsController#index action. All views use
214 | eRuby syntax by default.
215 |
216 | app/views/layouts
217 | Holds the template files for layouts to be used with views. This models the
218 | common header/footer method of wrapping views. In your views, define a layout
219 | using the layout :default and create a file named default.html.erb.
220 | Inside default.html.erb, call <% yield %> to render the view using this
221 | layout.
222 |
223 | app/helpers
224 | Holds view helpers that should be named like weblogs_helper.rb. These are
225 | generated for you automatically when using generators for controllers.
226 | Helpers can be used to wrap functionality for your views into methods.
227 |
228 | config
229 | Configuration files for the Rails environment, the routing map, the database,
230 | and other dependencies.
231 |
232 | db
233 | Contains the database schema in schema.rb. db/migrate contains all the
234 | sequence of Migrations for your schema.
235 |
236 | doc
237 | This directory is where your application documentation will be stored when
238 | generated using rake doc:app
239 |
240 | lib
241 | Application specific libraries. Basically, any kind of custom code that
242 | doesn't belong under controllers, models, or helpers. This directory is in
243 | the load path.
244 |
245 | public
246 | The directory available for the web server. Also contains the dispatchers and the
247 | default HTML files. This should be set as the DOCUMENT_ROOT of your web
248 | server.
249 |
250 | script
251 | Helper scripts for automation and generation.
252 |
253 | test
254 | Unit and functional tests along with fixtures. When using the rails generate
255 | command, template test files will be generated for you and placed in this
256 | directory.
257 |
258 | vendor
259 | External libraries that the application depends on. Also includes the plugins
260 | subdirectory. If the app has frozen rails, those gems also go here, under
261 | vendor/rails/. This directory is in the load path.
262 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/TopicsTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // LDTViewController.m
3 | // ldtrkpoc2
4 | //
5 | // Created by Shane Zatezalo on 12/8/11.
6 | // Copyright (c) 2011 Lottadot LLC All rights reserved.
7 | //
8 |
9 | #import "TopicsTableViewController.h"
10 | #import
11 | #import "CoreDataTableViewController.h"
12 | #import "MyModelEntities.h"
13 | #import
14 | #import "TopicEditorViewController.h"
15 |
16 | @interface TopicsTableViewController (Private)
17 | - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
18 | - (void)setupFetchedResultsController;
19 | - (void)fetchTopicDataFromRemote;
20 | - (void)deleteAllObjects:(NSString *)entityDescription;
21 | @end
22 |
23 | @implementation TopicsTableViewController
24 |
25 | - (void)didReceiveMemoryWarning
26 | {
27 | [super didReceiveMemoryWarning];
28 | // Release any cached data, images, etc that aren't in use.
29 | }
30 |
31 | #pragma mark - View lifecycle
32 |
33 | - (void)viewDidLoad
34 | {
35 | [super viewDidLoad];
36 | // Do any additional setup after loading the view, typically from a nib.
37 | }
38 |
39 | - (void)viewDidUnload
40 | {
41 | [super viewDidUnload];
42 | // Release any retained subviews of the main view.
43 | // e.g. self.myOutlet = nil;
44 | [[RKClient sharedClient].requestQueue cancelRequestsWithDelegate:self];
45 | }
46 |
47 | - (void)viewWillAppear:(BOOL)animated {
48 | [super viewWillAppear:animated];
49 |
50 | if (nil == self.fetchedResultsController) {
51 | [self setupFetchedResultsController];
52 | }
53 | [self fetchTopicDataFromRemote];
54 | }
55 |
56 | - (void)viewDidAppear:(BOOL)animated
57 | {
58 | [super viewDidAppear:animated];
59 | }
60 |
61 | - (void)viewWillDisappear:(BOOL)animated
62 | {
63 | [super viewWillDisappear:animated];
64 | }
65 |
66 | - (void)viewDidDisappear:(BOOL)animated
67 | {
68 | [super viewDidDisappear:animated];
69 | }
70 |
71 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
72 | {
73 | // Return YES for supported orientations
74 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
75 | }
76 |
77 | #pragma mark -
78 | #pragma mark Table view methods
79 |
80 |
81 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
82 |
83 | static NSString *reuseIdentifier = @"Topic Cell";
84 |
85 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
86 | if (nil == cell) {
87 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
88 | }
89 | [self configureCell:cell atIndexPath:indexPath];
90 | return cell;
91 | }
92 |
93 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
94 | if (editingStyle == UITableViewCellEditingStyleDelete) {
95 | // Delete the managed object for the given index path
96 |
97 | Topic *topic = (Topic *)[self.fetchedResultsController objectAtIndexPath:indexPath];
98 |
99 | if ([[topic topicID] intValue] <1) {
100 | // The topic was never synced to the Backend, just delete it from the MOC
101 | [[[[RKObjectManager sharedManager] objectStore] managedObjectContext ] deleteObject:topic];
102 | } else {
103 | [[RKObjectManager sharedManager] deleteObject:topic delegate:self];
104 | }
105 | }
106 | }
107 |
108 | #pragma mark - Table Cell
109 |
110 | - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
111 | //TODO
112 | Topic *topic = (Topic *)[self.fetchedResultsController objectAtIndexPath:indexPath];
113 | //cell.textLabel.text = @"something"; // [[aPost objectAtIndex:indexPath.row] title];
114 | cell.textLabel.text = [topic title];
115 |
116 | NSString *subTitle = [topic body];
117 | NSRange stringRange = {0, MIN([subTitle length], 40)};
118 | // adjust the range to include dependent chars
119 | stringRange = [subTitle rangeOfComposedCharacterSequencesForRange:stringRange];
120 | cell.detailTextLabel.text = [subTitle substringWithRange:stringRange];
121 | }
122 |
123 |
124 | #pragma mark -
125 | #pragma mark Fetched results controller
126 |
127 | /*
128 | Described by: Panupan Sriautharawong
129 | Restkit keeps one managed object context (MOC) per thread. Since
130 | remoting is asynchronous, the calls and work occur on a separate
131 | thread, and when the response comes back, Restkit does the work in a
132 | MOC on that thread. Don't worry though, Restkit merges these changes
133 | back to the main MOC for you automatically. Bottom line is, your
134 | application should use the main MOC retrievable at: [[RKObjectManager
135 | sharedManager].objectStore managedObjectContext].
136 | */
137 |
138 | - (void)setupFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
139 | {
140 | if (nil == self.fetchedResultsController) {
141 | //Ancient Way:
142 | //Normally one would use the MOC From the Main Thread/AppDelegate to fetch against
143 | //However with RestKit we do not need to.
144 | //NSManagedObjectContext *managedObjectContext = [ApplicationDelegate managedObjectContext];
145 |
146 | // // Old Way
147 | // // We'd create a FetchRequest and tell the request to use the Moc from RestKit
148 | // NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Topic"];
149 | // request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]];
150 | // // no predicate because we want ALL the Topics
151 | //
152 | // self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
153 | // //managedObjectContext:managedObjectContext
154 | // managedObjectContext: [[RKObjectManager
155 | // sharedManager].objectStore managedObjectContext]
156 | // sectionNameKeyPath:nil
157 | // cacheName:nil];
158 |
159 |
160 | self.fetchedResultsController = [Topic fetchAllSortedBy:@"title" ascending:YES withPredicate:nil groupBy:nil];
161 |
162 | }
163 | }
164 |
165 | - (void)fetchTopicDataFromRemote {
166 | // Load the object model via RestKit
167 | RKObjectManager* objectManager = [RKObjectManager sharedManager];
168 | [objectManager loadObjectsAtResourcePath:@"/topics" delegate:self
169 | block:^(RKObjectLoader* loader) {
170 | // The backend returns topics as a naked array in JSON, so we instruct the loader
171 | // to user the appropriate object mapping
172 | loader.objectMapping = [objectManager.mappingProvider objectMappingForClass:[Topic class]];
173 | }];
174 | }
175 |
176 | #pragma mark -
177 | #pragma mark RKObjectLoaderDelegate methods
178 |
179 | - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
180 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"LastUpdatedAt"];
181 | [[NSUserDefaults standardUserDefaults] synchronize];
182 | NSLog(@"Loaded topics: %@", objects);
183 | //[self loadObjectsFromDataStore];
184 | [self performFetch];
185 | }
186 |
187 | - (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
188 | UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Error"
189 | message:[error localizedDescription]
190 | delegate:nil
191 | cancelButtonTitle:@"OK" otherButtonTitles:nil];
192 |
193 | [alert show];
194 | NSLog(@"Hit error: %@", error);
195 | }
196 |
197 | #pragma mark Segue
198 |
199 | // Support segueing from this table to any view controller that has a Topic @property.
200 |
201 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
202 | NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
203 | Topic *clicked = [self.fetchedResultsController objectAtIndexPath:indexPath];
204 | // be somewhat generic here (slightly advanced usage)
205 | // we'll segue to ANY view controller that has a photographer @property
206 | if ([@"addTopic" isEqualToString:segue.identifier]) {
207 | /*
208 | the segue’s destinationViewController is not the editor view controller, but rather a navigation controller
209 | */
210 | Topic *newTopic = nil;
211 | newTopic = (Topic *)[NSEntityDescription
212 | insertNewObjectForEntityForName:@"Topic"
213 | inManagedObjectContext:self.fetchedResultsController.managedObjectContext];
214 |
215 | [newTopic setTitle:@"title text"];
216 | [newTopic setBody:@"body text"];
217 |
218 | UIViewController *topVC = [[segue destinationViewController] topViewController];
219 | TopicEditorViewController *editor = (TopicEditorViewController *)topVC;
220 | editor.topic = newTopic;
221 | editor.topicsViewController = self;
222 | } else if ([segue.destinationViewController respondsToSelector:@selector(setTopic:)]) {
223 | // use performSelector:withObject: to send without compiler checking
224 | // (which is acceptable here because we used introspection to be sure this is okay)
225 | [segue.destinationViewController performSelector:@selector(setTopic:) withObject:clicked];
226 | }
227 | }
228 |
229 | #pragma mark Actions
230 |
231 | // back from the editting controller
232 |
233 | - (void)finishedEditing:(Topic *)aTopic AndCancelled:(BOOL)cancelled {
234 | if (nil != aTopic && !cancelled) {
235 | // Rails 3 defaults to not encapsulating the returned object { "topic" : { "id" : 999, ....
236 | // The only way this will work,
237 | // http://groups.google.com/group/restkit/browse_thread/thread/2463f121ae851976/c4f46703ddbedc6b?lnk=gst&q=postObject+block#c4f46703ddbedc6b
238 |
239 | [[RKObjectManager sharedManager] postObject:aTopic delegate:self block:^(RKObjectLoader* loader) {
240 | loader.resourcePath = @"/topics";
241 | // if you don't want to map the response back onto the original object being POST'd,
242 | // you can just nil out the targetObject.
243 | // When the target object is nil RestKit will instantiate new target
244 | // objects (or look them up if using Core Data)
245 | //loader.targetObject = nil;
246 | loader.objectMapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:@"/topics"];
247 | }];
248 |
249 | } else if (nil != aTopic && cancelled) {
250 | if ([[aTopic topicID] intValue] <1) {
251 | // The topic was a new topic, but it was cancelled. It needs to be deleted out of the MOC
252 | // Normally, we would used RestKit's ObjectManager to delete the object. It would contact the remote server and delete it there too.
253 | // But doing this for an object that has no remote key (Topic.topicID) will cause Restkit to throw an
254 | // 'Unable to find a routable path for object of type '(null)' for HTTP Method 'DELETE''
255 | // so rather then do this
256 | //[[RKObjectManager sharedManager] deleteObject:aTopic delegate:self];
257 | // we delete it right out of the MOC
258 | [[[[RKObjectManager sharedManager] objectStore] managedObjectContext ] deleteObject:aTopic];
259 | }
260 | }
261 | [self dismissModalViewControllerAnimated:YES];
262 | }
263 |
264 | - (IBAction)deleteAllButtonClicked:(id)sender {
265 | NSArray* objects = [Topic findAll];
266 | for (Topic *object in objects) {
267 | [[Topic managedObjectContext] deleteObject:object];
268 | }
269 | NSError* error = nil;
270 | [[Topic managedObjectContext] save:&error];
271 | if (nil != error) {
272 | // Error checking here...
273 | }
274 | [self.tableView reloadData];
275 | }
276 |
277 | - (IBAction)refreshButtonClicked:(id)sender {
278 | [self fetchTopicDataFromRemote];
279 | }
280 |
281 | @end
282 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/PostsTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PostsTableViewController.m
3 | // ldtrkpoc2
4 | //
5 | // Created by Shane Zatezalo on 12/13/11.
6 | // Copyright (c) 2011 Lottadot LLC All rights reserved.
7 | //
8 |
9 | #import "PostsTableViewController.h"
10 | #import
11 | #import "CoreDataTableViewController.h"
12 | #import "MyModelEntities.h"
13 | #import
14 | #import "PostEditorViewController.h"
15 |
16 | @interface PostsTableViewController ()
17 | - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
18 | - (void)setupPostsFetchedResultsController;
19 | - (void)fetchPostsDataFromRemote;
20 | - (NSIndexPath *)indexPathForObject:(id)object;
21 | @end
22 |
23 | @implementation PostsTableViewController
24 |
25 | @synthesize topic = _topic;
26 |
27 | - (void)didReceiveMemoryWarning
28 | {
29 | [super didReceiveMemoryWarning];
30 | // Release any cached data, images, etc that aren't in use.
31 | }
32 |
33 | #pragma mark - View lifecycle
34 |
35 | - (void)viewDidLoad
36 | {
37 | [super viewDidLoad];
38 | // Do any additional setup after loading the view, typically from a nib.
39 | NSLog(@"viewDidLoad");
40 | [self fetchPostsDataFromRemote];
41 | }
42 |
43 | - (void)viewDidUnload
44 | {
45 | [super viewDidUnload];
46 | self.debug = YES;
47 | [[RKClient sharedClient].requestQueue cancelRequestsWithDelegate:self];
48 | }
49 |
50 | - (void)viewWillAppear:(BOOL)animated {
51 | [super viewWillAppear:animated];
52 |
53 | if (nil == self.fetchedResultsController) {
54 | [self setupPostsFetchedResultsController];
55 |
56 | }
57 | self.debug = YES;
58 | //[self performFetch];
59 | NSLog(@"viewWillAppear count:%i",[[self.fetchedResultsController sections] count]);
60 | //[self.tableView reloadData];
61 |
62 | }
63 |
64 | - (void)viewDidAppear:(BOOL)animated
65 | {
66 | [super viewDidAppear:animated];
67 | }
68 |
69 | - (void)viewWillDisappear:(BOOL)animated
70 | {
71 | // Depricated? No need for this?
72 | //[[RKRequestQueue sharedQueue] cancelRequestsWithDelegate:self];
73 | [super viewWillDisappear:animated];
74 | }
75 |
76 | - (void)viewDidDisappear:(BOOL)animated
77 | {
78 | [super viewDidDisappear:animated];
79 | }
80 |
81 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
82 | {
83 | // Return YES for supported orientations
84 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
85 | }
86 |
87 | #pragma mark -
88 | #pragma mark Table view methods
89 |
90 |
91 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
92 |
93 | static NSString *reuseIdentifier = @"Post Cell";
94 |
95 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
96 | if (nil == cell) {
97 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
98 | }
99 | [self configureCell:cell atIndexPath:indexPath];
100 | return cell;
101 | }
102 |
103 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
104 | if (editingStyle == UITableViewCellEditingStyleDelete) {
105 | // Delete the managed object for the given index path
106 |
107 | Post *post = (Post *)[self.fetchedResultsController objectAtIndexPath:indexPath];
108 |
109 | if ([[post postID] intValue] <1) {
110 | // The topic was never synced to the Backend, just delete it from the MOC
111 | [[[[RKObjectManager sharedManager] objectStore] managedObjectContext ] deleteObject:post];
112 | } else {
113 | [[RKObjectManager sharedManager] deleteObject:post delegate:self];
114 | }
115 | }
116 | }
117 |
118 | - (NSIndexPath *)indexPathForObject:(id)object {
119 | NSIndexPath *returnValue = nil;
120 | NSArray *visible = [self.tableView indexPathsForVisibleRows];
121 | for (int i=0; i < [visible count]; i++) {
122 | NSIndexPath *indexPath = (NSIndexPath*)[visible objectAtIndex:i];
123 | //id rowObject = [self.tableView objectAtIndex:indexPath.row];
124 | id rowObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
125 |
126 |
127 | if ([rowObject isEqual:object]) {
128 | returnValue = indexPath;
129 | }
130 | }
131 | return returnValue;
132 | }
133 |
134 | #pragma mark - Table Cell
135 |
136 | - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
137 | //TODO
138 | Post *post = [self.fetchedResultsController objectAtIndexPath:indexPath];
139 | //cell.textLabel.text = @"something"; // [[aPost objectAtIndex:indexPath.row] title];
140 | cell.textLabel.text = [NSString stringWithFormat:@"%@ (id:%i)",[post title],[[post postID] intValue]];
141 |
142 | NSString *subTitle = [[post author] userName];
143 | NSRange stringRange = {0, MIN([subTitle length], 40)};
144 | // adjust the range to include dependent chars
145 | stringRange = [subTitle rangeOfComposedCharacterSequencesForRange:stringRange];
146 | cell.detailTextLabel.text = [subTitle substringWithRange:stringRange];
147 | }
148 |
149 |
150 | #pragma mark -
151 | #pragma mark Fetched results controller
152 |
153 | - (void)setupPostsFetchedResultsController // attaches an NSFetchRequest to this UITableViewController
154 | {
155 | /* TODO Possibly use simpler fetching
156 | NSFetchRequest *request = [Post fetchRequest];
157 |
158 | request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]];
159 | request.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"topicID = %i",[self.topic.topicID intValue]]];
160 |
161 | return [NSArray arrayWithObject:request];
162 | */
163 |
164 | if (nil == self.fetchedResultsController) {
165 | //NSManagedObjectContext *managedObjectContext = [ApplicationDelegate managedObjectContext];
166 |
167 |
168 | NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Post"];
169 | request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]];
170 | // a predicate because we want ALL the Posts that belong to the topic
171 | //request.predicate = [NSPredicate predicateWithFormat:@"post.topicID = %@", self.topic.topicID];
172 | request.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"topicID = %i",[self.topic.topicID intValue]]];
173 | self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
174 | managedObjectContext:self.topic.managedObjectContext
175 | sectionNameKeyPath:nil
176 | cacheName:nil];
177 |
178 |
179 | }
180 | }
181 |
182 | - (void)fetchPostsDataFromRemote {
183 |
184 | // Load the object model via RestKit
185 | RKObjectManager* objectManager = [RKObjectManager sharedManager];
186 | NSString *url = [NSString stringWithFormat:@"/topics/%d/posts",[[self.topic topicID] intValue]];
187 | [objectManager loadObjectsAtResourcePath:url delegate:self
188 | block:^(RKObjectLoader* loader) {
189 | // The backend returns posts as a naked array in JSON, so we instruct the loader
190 | // to user the appropriate object mapping
191 | loader.objectMapping = [objectManager.mappingProvider objectMappingForClass:[Post class]];
192 | }];
193 | }
194 |
195 | #pragma mark - RKObjectLoaderDelegate methods
196 |
197 | - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
198 | [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"LastUpdatedAt"];
199 | [[NSUserDefaults standardUserDefaults] synchronize];
200 | NSLog(@"objectLoader didLoadObjects: %@", objects);
201 | //[self loadObjectsFromDataStore];
202 | //[self performFetch];
203 |
204 | //NSDictionary* params = [NSDictionary dictionaryWithObject:@"RestKit" forKey:@"Sender"];
205 |
206 | [self.tableView reloadData];
207 | }
208 |
209 | - (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error {
210 | UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Error"
211 | message:[error localizedDescription]
212 | delegate:nil
213 | cancelButtonTitle:@"OK" otherButtonTitles:nil];
214 |
215 | [alert show];
216 | NSLog(@"Hit error: %@", error);
217 | }
218 |
219 | - (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObject:(id)object {
220 | if ([object class] == [Post class]) {
221 | NSLog(@"*********************** objectLoader didLoadObject Post: id: %i",[[object postID] intValue]);
222 | /* we pushed a Post object to the Server and are notified by RestKit's RKObjectLoader's Delegate Protocol that it was a success.
223 | If it was a new object, the new object would have a new ID value, so the table should be updated
224 | */
225 | //[self.tableView reloadData];
226 | NSIndexPath *indexPath = [self indexPathForObject:object];
227 | if (indexPath) {
228 | [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
229 | }
230 |
231 | }
232 |
233 | }
234 |
235 | #pragma mark topic
236 |
237 | - (void)setTopic:(Topic *)topic {
238 | _topic = topic;
239 | self.title = topic.title;
240 | [self setupPostsFetchedResultsController];
241 | }
242 |
243 |
244 | #pragma mark Segue
245 |
246 | // Support segueing from this table to any view controller that has a Post @property.
247 |
248 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
249 | NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
250 | Post *clicked = [self.fetchedResultsController objectAtIndexPath:indexPath];
251 | // // be somewhat generic here (slightly advanced usage)
252 | // // we'll segue to ANY view controller that has a photographer @property
253 | // if ([segue.destinationViewController respondsToSelector:@selector(setPost:)]) {
254 | // // use performSelector:withObject: to send without compiler checking
255 | // // (which is acceptable here because we used introspection to be sure this is okay)
256 | // [segue.destinationViewController performSelector:@selector(setPost:) withObject:clicked];
257 | // }
258 | // be somewhat generic here (slightly advanced usage)
259 | // we'll segue to ANY view controller that has a photographer @property
260 | if ([@"addPost" isEqualToString:segue.identifier]) {
261 | /*
262 | the segue’s destinationViewController is not the editor view controller, but rather a navigation controller
263 | */
264 | // Post *newPost = nil;
265 | // newPost = (Post *)[NSEntityDescription
266 | // insertNewObjectForEntityForName:@"Post"
267 | // inManagedObjectContext:self.fetchedResultsController.managedObjectContext];
268 |
269 | Author *author;
270 | //NSArray *authorsSorted = [Author findAllSortedByProperty:@"userName" ascending: YES];
271 | NSFetchRequest *request = [Author fetchRequest];
272 | NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"userName" ascending:YES];
273 | [request setSortDescriptors:[NSArray arrayWithObject:descriptor]];
274 | NSArray *authors = [Author objectsWithFetchRequest:request];
275 | if (nil != authors && [authors count]) {
276 | author = [authors lastObject];
277 | }
278 |
279 | /* Create the new "empty" Post */
280 | Post *newPost = [Post object];
281 |
282 |
283 | [newPost setTitle:@"title text"];
284 | [newPost setBody:@"body text"];
285 |
286 | // Set this new Post's Topic
287 | [newPost setTopic:self.topic];
288 | [newPost setTopicID:self.topic.topicID];
289 |
290 | if (nil != author) {
291 | // Set this new Post's Author
292 | [newPost setAuthor:author];
293 | [newPost setAuthorID:author.authorID];
294 | }
295 |
296 | UIViewController *topVC = [[segue destinationViewController] topViewController];
297 | PostEditorViewController *editor = (PostEditorViewController *)topVC;
298 | editor.post = newPost;
299 | editor.postsViewController = self;
300 | } else if ([segue.destinationViewController respondsToSelector:@selector(setPost:)]) {
301 | // use performSelector:withObject: to send without compiler checking
302 | // (which is acceptable here because we used introspection to be sure this is okay)
303 | [segue.destinationViewController performSelector:@selector(setPost:) withObject:clicked];
304 | }
305 | }
306 |
307 | #pragma mark Actions
308 |
309 | // back from the editting controller
310 |
311 | - (void)finishedEditing:(Post *)aPost AndCancelled:(BOOL)cancelled {
312 | if (nil != aPost && !cancelled) {
313 | // Rails 3 defaults to not encapsulating the returned object { "post" : { "id" : 999, ....
314 | // The only way this will work,
315 | // http://groups.google.com/group/restkit/browse_thread/thread/2463f121ae851976/c4f46703ddbedc6b?lnk=gst&q=postObject+block#c4f46703ddbedc6b
316 |
317 | [[RKObjectManager sharedManager] postObject:aPost delegate:self block:^(RKObjectLoader* loader) {
318 | loader.resourcePath = @"/posts";
319 | // if you don't want to map the response back onto the original object being POST'd,
320 | // you can just nil out the targetObject.
321 | // When the target object is nil RestKit will instantiate new target
322 | // objects (or look them up if using Core Data)
323 | //loader.targetObject = nil;
324 | loader.objectMapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:@"/posts"];
325 | }];
326 |
327 |
328 | } else if (nil != aPost && cancelled) {
329 | if ([[aPost postID] intValue] <1) {
330 | // The post was a new post, but it was cancelled. It needs to be deleted out of the MOC
331 | // Normally, we would used RestKit's ObjectManager to delete the object. It would contact the remote server and delete it there too.
332 | // But doing this for an object that has no remote key (Topic.topicID) will cause Restkit to throw an
333 | // 'Unable to find a routable path for object of type '(null)' for HTTP Method 'DELETE''
334 | // so rather then do this
335 | //[[RKObjectManager sharedManager] deleteObject:aTopic delegate:self];
336 | // we delete it right out of the MOC
337 | [[[[RKObjectManager sharedManager] objectStore] managedObjectContext ] deleteObject:aPost];
338 | }
339 | }
340 | [self dismissModalViewControllerAnimated:YES];
341 | }
342 |
343 | @end
344 |
--------------------------------------------------------------------------------
/iOS/ldtrkpoc2/ldtrkpoc2/LDTAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // LDTAppDelegate.m
3 | // ldtrkpoc2
4 | //
5 | // Created by Shane Zatezalo on 12/8/11.
6 | // Copyright (c) 2011 Lottadot LLC. All rights reserved.
7 | //
8 |
9 | #import "LDTAppDelegate.h"
10 | #import "MyModelEntities.h"
11 | #import
12 | #import
13 |
14 | @interface LDTAppDelegate (Private)
15 | - (void)setupRestKit;
16 | @end;
17 |
18 | @implementation LDTAppDelegate
19 |
20 | @synthesize window = _window;
21 | @synthesize managedObjectContext = __managedObjectContext;
22 | @synthesize managedObjectModel = __managedObjectModel;
23 | @synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
24 |
25 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
26 | {
27 | // Override point for customization after application launch.
28 | [self setupRestKit];
29 | return YES;
30 | }
31 |
32 | - (void)applicationWillResignActive:(UIApplication *)application
33 | {
34 | /*
35 | Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
36 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
37 | */
38 | }
39 |
40 | - (void)applicationDidEnterBackground:(UIApplication *)application
41 | {
42 | /*
43 | Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
44 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
45 | */
46 | }
47 |
48 | - (void)applicationWillEnterForeground:(UIApplication *)application
49 | {
50 | /*
51 | Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
52 | */
53 | }
54 |
55 | - (void)applicationDidBecomeActive:(UIApplication *)application
56 | {
57 | /*
58 | Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
59 | */
60 | }
61 |
62 | - (void)applicationWillTerminate:(UIApplication *)application
63 | {
64 | /*
65 | Called when the application is about to terminate.
66 | Save data if appropriate.
67 | See also applicationDidEnterBackground:.
68 | */
69 | }
70 |
71 | - (void)saveContext
72 | {
73 | NSError *error = nil;
74 | NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
75 | if (managedObjectContext != nil)
76 | {
77 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
78 | {
79 | /*
80 | Replace this implementation with code to handle the error appropriately.
81 |
82 | abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
83 | */
84 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
85 | abort();
86 | }
87 | }
88 | }
89 |
90 | #pragma mark - Restkit Stack
91 |
92 | /*
93 | Setup Restkit with debug-logging to the console so we can see what's going on
94 | */
95 |
96 | - (void)setupRestKit {
97 | RKClient *client = [RKClient clientWithBaseURL:LDTHOSTNAME];
98 | NSLog(@"Configured RestKit Client: %@", client);
99 |
100 | // See RKLog.h for more info on using the logging system to debug.
101 | RKLogConfigureByName("RestKit", RKLogLevelTrace);
102 | RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
103 | RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
104 | RKLogConfigureByName("RestKit/Network/Queue", RKLogLevelTrace);
105 |
106 | // Enable automatic network activity indicator management
107 | client.requestQueue.showsNetworkActivityIndicatorWhenBusy = YES;
108 |
109 | //Setup Restkit Mappings
110 | RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:LDTHOSTNAME];
111 |
112 | // Enable automatic network activity indicator management
113 | objectManager.client.requestQueue.showsNetworkActivityIndicatorWhenBusy = YES;
114 |
115 | objectManager.acceptMIMEType = RKMIMETypeJSON;
116 | objectManager.serializationMIMEType = RKMIMETypeJSON;
117 |
118 |
119 | /*
120 | We want to initialize RestKit with a Core Data Managed Object Store, backed by a SQLLite file.
121 | If we provide a seed database, we can pass that in as well.
122 | RestKit's objectStoreWithStoreFilename will take care of creating, seeding, and merging from
123 | main bundle for you.
124 |
125 | Note that objectStoreWithStoreFilename will end using initWithStoreFilename which will
126 | retain the Moc.
127 | */
128 |
129 | NSString *seedDatabaseName = nil;
130 | NSString *databaseName = @"ldtrkpoc2.sqlite";
131 | objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:databaseName
132 | usingSeedDatabaseName:seedDatabaseName
133 | managedObjectModel:nil
134 | delegate:self];
135 |
136 | #pragma mark - Reskit Mappings
137 |
138 | //RKManagedObjectMapping *topicMapping = [RKObjectMapping mappingForClass:[Topic class]];
139 | RKManagedObjectMapping *topicMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Topic"];
140 | RKManagedObjectMapping *postMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Post"];
141 | RKManagedObjectMapping *authorMapping = [RKManagedObjectMapping mappingForEntityWithName:@"Author"];
142 |
143 | #pragma mark - Restkit Topic Setup
144 |
145 | [topicMapping mapKeyPathsToAttributes:@"id", @"topicID",
146 | @"title", @"title",
147 | @"body", @"body",
148 | nil];
149 | [topicMapping setPrimaryKeyAttribute:@"topicID"];
150 | //topicMapping.primaryKeyAttribute = @"topicID";
151 | [topicMapping mapRelationship:@"topic" withMapping:topicMapping];
152 | [topicMapping mapRelationship:@"post" withMapping:postMapping];
153 |
154 | //TODO: evaluate declaring the relationships like this
155 | // [albumMapping mapKeyPath:@"presentations" toRelationship:@"presentations" withMapping:presentationMapping];
156 | // so we might try
157 | // [topicMapping mapKeyPath:@"posts" toRelationship:@"posts" withMapping:postMapping];
158 | // [postMapping mapKeyPath:@"author" toRelationship:@"author" withMapping:authorMapping];
159 |
160 | // On a Topic the forKeyPath must be @"" rather then @"/topics"
161 | [objectManager.mappingProvider setMapping:topicMapping forKeyPath:@"/topics"];
162 |
163 | // Configure the Serialization mapping for a Widget. Without this a PostObject will fail
164 | // This post was helpful: https://groups.google.com/group/restkit/browse_frm/thread/959b6e30c86d257f/e0bc0a37b46c18a5?lnk=gst&q=You+must+provide+a+serialization+mapping+for+objects+of+type#e0bc0a37b46c18a5
165 | RKObjectMapping *topicSerializationMapping = [RKObjectMapping
166 | mappingForClass:[Topic class]];
167 | [topicSerializationMapping mapKeyPath:@"topicID"
168 | toAttribute:@"id"];
169 | [topicSerializationMapping mapKeyPath:@"title"
170 | toAttribute:@"title"];
171 | [topicSerializationMapping mapKeyPath:@"body"
172 | toAttribute:@"body"];
173 |
174 | [objectManager.mappingProvider
175 | setSerializationMapping:topicSerializationMapping forClass:[Topic class]];
176 |
177 | // Configure a default resource path for Topics.
178 | // Will send GET, PUT, and DELETE requests to '/topics/XXXX'
179 | // topicID is a property on the Topic class
180 | [objectManager.router routeClass:[Topic class] toResourcePath:@"/topics/:topicID"];
181 |
182 | // Send POST requests for instances of Topic to '/topics'
183 | [objectManager.router routeClass:[Topic class] toResourcePath:@"/topics" forMethod:RKRequestMethodPOST];
184 | [objectManager.router routeClass:[Topic class] toResourcePath:@"/topics/(topicID)" forMethod:RKRequestMethodPUT];
185 | [objectManager.router routeClass:[Topic class] toResourcePath:@"/topics/(topicID)" forMethod:RKRequestMethodDELETE];
186 |
187 | #pragma mark - Reskit Post Model Setup
188 |
189 | [postMapping mapKeyPathsToAttributes:@"id", @"postID",
190 | @"title", @"title",
191 | @"body", @"body",
192 | @"topic_id", @"topicID",
193 | @"author_id", @"authorID",
194 | nil];
195 | postMapping.primaryKeyAttribute = @"postID";
196 | //[postMapping mapKeyPath:@"user_id" toAttribute:@"userID"];
197 | //#[postMapping mapKeyPath:@"topic_id" toAttribute:@"topicID"];
198 |
199 | [postMapping mapRelationship:@"post" withMapping:postMapping];
200 | [postMapping mapRelationship:@"topic" withMapping:topicMapping];
201 | [postMapping mapRelationship:@"author" withMapping:authorMapping];
202 |
203 | [objectManager.mappingProvider setMapping:postMapping forKeyPath:@"/posts"];
204 |
205 | // Tried this, was "too deep"
206 | // RKObjectMapping *postSerializationMapping = [postMapping inverseMapping];
207 | RKObjectMapping *postSerializationMapping = [RKObjectMapping
208 | mappingForClass:[Post class]];
209 | [postSerializationMapping mapKeyPath:@"postID"
210 | toAttribute:@"id"];
211 | [postSerializationMapping mapKeyPath:@"title"
212 | toAttribute:@"title"];
213 | [postSerializationMapping mapKeyPath:@"body"
214 | toAttribute:@"body"];
215 | [postSerializationMapping mapKeyPath:@"topicID"
216 | toAttribute:@"topic_id"];
217 | [postSerializationMapping mapKeyPath:@"authorID"
218 | toAttribute:@"author_id"];
219 |
220 | [objectManager.mappingProvider
221 | setSerializationMapping:postSerializationMapping forClass:[Post class]];
222 |
223 | [objectManager.router routeClass:[Post class] toResourcePath:@"/posts/:postID"];
224 |
225 | [objectManager.router routeClass:[Post class] toResourcePath:@"/posts" forMethod:RKRequestMethodPOST];
226 |
227 | //TODO: Evaluate using :'s in routes
228 | // :list.listID/tasks/:taskID
229 | // [objectManager.router routeClass:[Post class] toResourcePath:@"/topics/:topic.topicID/posts/:postID"];
230 |
231 | #pragma mark - Reskit Author Model Setup
232 |
233 | [authorMapping mapKeyPathsToAttributes:@"id", @"authorID",
234 | @"email", @"email",
235 | @"username", @"userName",
236 | nil];
237 | authorMapping.primaryKeyAttribute = @"authorID";
238 |
239 | //[authorMapping mapRelationship:@"post" withMapping:postMapping];
240 |
241 | [objectManager.mappingProvider setMapping:authorMapping forKeyPath:@"/authors"];
242 |
243 | RKObjectMapping *authorSerializationMapping = [RKObjectMapping
244 | mappingForClass:[Author class]];
245 | [authorSerializationMapping mapKeyPath:@"authorID"
246 | toAttribute:@"id"];
247 | [authorSerializationMapping mapKeyPath:@"email"
248 | toAttribute:@"email"];
249 | [authorSerializationMapping mapKeyPath:@"userName"
250 | toAttribute:@"username"];
251 |
252 | [objectManager.mappingProvider
253 | setSerializationMapping:authorSerializationMapping forClass:[Author class]];
254 |
255 | [objectManager.router routeClass:[Author class] toResourcePath:@"/authors/:authorID"];
256 |
257 | [objectManager.router routeClass:[Author class] toResourcePath:@"/authors" forMethod:RKRequestMethodPOST];
258 | }
259 |
260 | //- (BOOL) isDatabaseResetNeeded {
261 | // [[NSUserDefaults standardUserDefaults] synchronize];
262 | // BOOL needsReset = [[NSUserDefaults standardUserDefaults] boolForKey:kResetSavedDatabaseKey];
263 | //
264 | // if (needsReset) {
265 | //
266 | // [SLFAlertView showWithTitle:NSLocalizedStringFromTable(@"Settings: Reset Data to Factory?", @"AppAlerts", @"Confirmation to delete and reset the app's database.")
267 | // message:NSLocalizedStringFromTable(@"Are you sure you want to reset the legislative database? NOTE: The application may quit after this reset. New data will be downloaded automatically via the Internet during the next app launch.", @"AppAlerts",@"")
268 | // cancelTitle:NSLocalizedStringFromTable(@"Cancel",@"StandardUI",@"Cancelling some activity")
269 | // cancelBlock:^(void)
270 | // {
271 | // [self doDataReset:NO];
272 | // }
273 | // otherTitle:NSLocalizedStringFromTable(@"Reset", @"StandardUI", @"Reset application settings to defaults")
274 | // otherBlock:^(void)
275 | // {
276 | // [self doDataReset:YES];
277 | // }];
278 | // }
279 | // return needsReset;
280 | //}
281 | //
282 | //- (void)doDataReset:(BOOL)doReset {
283 | // [[NSUserDefaults standardUserDefaults] setBool:NO forKey:kResetSavedDatabaseKey];
284 | // [[NSUserDefaults standardUserDefaults] synchronize];
285 | //
286 | // if (doReset) {
287 | // [self resetSavedDatabase:nil];
288 | // }
289 | //}
290 | //
291 | //- (void) resetSavedDatabase:(id)sender {
292 | // RKManagedObjectStore *objectStore = [[RKObjectManager sharedManager] objectStore];
293 | // [objectStore deletePersistantStore];
294 | // [objectStore save];
295 | // [[NSNotificationCenter defaultCenter] postNotificationName:@"DATA_STORE_RELOAD" object:nil];
296 | //
297 | //}
298 |
299 | #pragma mark - Core Data stack
300 |
301 | /**
302 | Returns the managed object context for the application.
303 | If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
304 | */
305 | - (NSManagedObjectContext *)managedObjectContext
306 | {
307 | if (__managedObjectContext != nil)
308 | {
309 | return __managedObjectContext;
310 | }
311 |
312 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
313 | if (coordinator != nil)
314 | {
315 | __managedObjectContext = [[NSManagedObjectContext alloc] init];
316 | [__managedObjectContext setPersistentStoreCoordinator:coordinator];
317 | }
318 | return __managedObjectContext;
319 | }
320 |
321 | /**
322 | Returns the managed object model for the application.
323 | If the model doesn't already exist, it is created from the application's model.
324 | */
325 | - (NSManagedObjectModel *)managedObjectModel
326 | {
327 | if (__managedObjectModel != nil)
328 | {
329 | return __managedObjectModel;
330 | }
331 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"ldtrkpoc2" withExtension:@"momd"];
332 | __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
333 | return __managedObjectModel;
334 | }
335 |
336 | /**
337 | Returns the persistent store coordinator for the application.
338 | If the coordinator doesn't already exist, it is created and the application's store added to it.
339 | */
340 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator
341 | {
342 | if (__persistentStoreCoordinator != nil)
343 | {
344 | return __persistentStoreCoordinator;
345 | }
346 |
347 | NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"ldtrkpoc2.sqlite"];
348 |
349 | NSError *error = nil;
350 | __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
351 | if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
352 | {
353 | /*
354 | Replace this implementation with code to handle the error appropriately.
355 |
356 | abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
357 |
358 | Typical reasons for an error here include:
359 | * The persistent store is not accessible;
360 | * The schema for the persistent store is incompatible with current managed object model.
361 | Check the error message to determine what the actual problem was.
362 |
363 |
364 | If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
365 |
366 | If you encounter schema incompatibility errors during development, you can reduce their frequency by:
367 | * Simply deleting the existing store:
368 | [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
369 |
370 | * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
371 | [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
372 |
373 | Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
374 |
375 | */
376 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
377 | abort();
378 | }
379 |
380 | return __persistentStoreCoordinator;
381 | }
382 |
383 | #pragma mark - Application's Documents directory
384 |
385 | /**
386 | Returns the URL to the application's Documents directory.
387 | */
388 | - (NSURL *)applicationDocumentsDirectory
389 | {
390 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
391 | }
392 |
393 |
394 | @end
395 |
--------------------------------------------------------------------------------