{"action":"created","comment":{"url":"https://api.github.com/repos/hack4impact/maps4all/pulls/comments/60005649","id":60005649,"diff_hunk":"@@ -45,24 +59,108 @@ def create():\n def edit(resource_id):\n     \"\"\"Edit a resource.\"\"\"\n     resource = Resource.query.get(resource_id)\n-    field_names = Resource.__table__.columns.keys()\n+    if resource is None:\n+        abort(404)\n+    resource_field_names = Resource.__table__.columns.keys()\n+    descriptors = Descriptor.query.all()\n+    for descriptor in descriptors:\n+        # fields for option descriptors\n+        if (descriptor.values):\n+            choices = [(str(i), v) for i, v in enumerate(descriptor.values)]\n+            default = None\n+            option_association = OptionAssociation.query.filter_by(\n+                resource_id=resource_id,\n+                descriptor_id=descriptor.id\n+            ).first()\n+            if (option_association is not None):\n+                default = option_association.option\n+            setattr(SingleResourceForm,\n+                    descriptor.name,\n+                    SelectField(choices=choices, default=default))\n+        # fields for text descriptors\n+        else:\n+            default = None\n+            text_association = TextAssociation.query.filter_by(\n+                resource_id=resource_id,\n+                descriptor_id=descriptor.id\n+            ).first()\n+            if (text_association is not None):\n+                default = text_association.text\n+            setattr(SingleResourceForm,\n+                    descriptor.name,\n+                    TextAreaField(default=default))\n     form = SingleResourceForm()\n     if form.validate_on_submit():\n-        resource.name = form.name.data\n-        resource.address = form.address.data\n-        resource.latitude = form.latitude.data\n-        resource.longitude = form.longitude.data\n+        # field id is not needed for the form, hence omitted with [1:]\n+        for field_name in resource_field_names[1:]:\n+            setattr(resource, field_name, form[field_name].data)\n+        save_associations(resource=resource,\n+                          form=form,\n+                          descriptors=descriptors,\n+                          resource_existed=True)\n         try:\n             db.session.commit()\n             flash('Resource updated', 'form-success')\n-            return redirect(url_for('single_resource.edit',\n-                                    resource_id=resource_id))\n+            return redirect(url_for('single_resource.index'))\n         except IntegrityError:\n             db.session.rollback()\n             flash('Error: failed to save resource. Please try again.',\n                   'form-error')\n-    for field_name in field_names[1:]:\n+    # field id is not needed for the form, hence omitted with [1:]\n+    for field_name in resource_field_names[1:]:\n         form[field_name].data = resource.__dict__[field_name]\n     return render_template('single_resource/edit.html',\n                            form=form,\n                            resource_id=resource_id)\n+\n+\n+def save_associations(resource, form, descriptors, resource_existed=True):\n+    \"\"\"Save associations from the forms received by 'create' and 'edit' route\n+    handlers to the database.\"\"\"\n+    for descriptor in descriptors:\n+        if (descriptor.values):\n+            AssociationClass = OptionAssociation\n+            value = int(form[descriptor.name].data)\n+            keyword = 'option'\n+        else:\n+            AssociationClass = TextAssociation\n+            value = form[descriptor.name].data\n+            keyword = 'text'\n+        association = None\n+        if (resource_existed):\n+            association = AssociationClass.query.filter_by(\n+                resource_id=resource.id,\n+                descriptor_id=descriptor.id\n+            ).first()\n+        if (association is not None):\n+            setattr(association, keyword, value)\n+        else:\n+            arguments = {'resource_id': resource.id,\n+                         'descriptor_id': descriptor.id,\n+                         keyword: value,\n+                         'resource': resource,\n+                         'descriptor': descriptor}\n+            new_association = AssociationClass(**arguments)\n+            db.session.add(new_association)","path":"app/single_resource/views.py","position":143,"original_position":143,"commit_id":"195e3d92be485b976cca733f45f31a7d835648e8","original_commit_id":"195e3d92be485b976cca733f45f31a7d835648e8","user":{"login":"weronica","id":3880084,"avatar_url":"https://avatars.githubusercontent.com/u/3880084?v=3","gravatar_id":"","url":"https://api.github.com/users/weronica","html_url":"https://github.com/weronica","followers_url":"https://api.github.com/users/weronica/followers","following_url":"https://api.github.com/users/weronica/following{/other_user}","gists_url":"https://api.github.com/users/weronica/gists{/gist_id}","starred_url":"https://api.github.com/users/weronica/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/weronica/subscriptions","organizations_url":"https://api.github.com/users/weronica/orgs","repos_url":"https://api.github.com/users/weronica/repos","events_url":"https://api.github.com/users/weronica/events{/privacy}","received_events_url":"https://api.github.com/users/weronica/received_events","type":"User","site_admin":false},"body":"But this is the last line in the function - where is `save_associations` called?","created_at":"2016-04-18T04:46:31Z","updated_at":"2016-04-18T04:46:31Z","html_url":"https://github.com/hack4impact/maps4all/pull/27#discussion_r60005649","pull_request_url":"https://api.github.com/repos/hack4impact/maps4all/pulls/27","_links":{"self":{"href":"https://api.github.com/repos/hack4impact/maps4all/pulls/comments/60005649"},"html":{"href":"https://github.com/hack4impact/maps4all/pull/27#discussion_r60005649"},"pull_request":{"href":"https://api.github.com/repos/hack4impact/maps4all/pulls/27"}}},"pull_request":{"url":"https://api.github.com/repos/hack4impact/maps4all/pulls/27","id":65942209,"html_url":"https://github.com/hack4impact/maps4all/pull/27","diff_url":"https://github.com/hack4impact/maps4all/pull/27.diff","patch_url":"https://github.com/hack4impact/maps4all/pull/27.patch","issue_url":"https://api.github.com/repos/hack4impact/maps4all/issues/27","number":27,"state":"open","locked":false,"title":"Add descriptor associations","user":{"login":"armant","id":6414384,"avatar_url":"https://avatars.githubusercontent.com/u/6414384?v=3","gravatar_id":"","url":"https://api.github.com/users/armant","html_url":"https://github.com/armant","followers_url":"https://api.github.com/users/armant/followers","following_url":"https://api.github.com/users/armant/following{/other_user}","gists_url":"https://api.github.com/users/armant/gists{/gist_id}","starred_url":"https://api.github.com/users/armant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/armant/subscriptions","organizations_url":"https://api.github.com/users/armant/orgs","repos_url":"https://api.github.com/users/armant/repos","events_url":"https://api.github.com/users/armant/events{/privacy}","received_events_url":"https://api.github.com/users/armant/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-04-11T05:34:08Z","updated_at":"2016-04-18T04:46:31Z","closed_at":null,"merged_at":null,"merge_commit_sha":"43c1b10216499243d77b22f0584949166fb3370b","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/hack4impact/maps4all/pulls/27/commits","review_comments_url":"https://api.github.com/repos/hack4impact/maps4all/pulls/27/comments","review_comment_url":"https://api.github.com/repos/hack4impact/maps4all/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hack4impact/maps4all/issues/27/comments","statuses_url":"https://api.github.com/repos/hack4impact/maps4all/statuses/195e3d92be485b976cca733f45f31a7d835648e8","head":{"label":"hack4impact:arman-add-descriptor-associations","ref":"arman-add-descriptor-associations","sha":"195e3d92be485b976cca733f45f31a7d835648e8","user":{"login":"hack4impact","id":9021093,"avatar_url":"https://avatars.githubusercontent.com/u/9021093?v=3","gravatar_id":"","url":"https://api.github.com/users/hack4impact","html_url":"https://github.com/hack4impact","followers_url":"https://api.github.com/users/hack4impact/followers","following_url":"https://api.github.com/users/hack4impact/following{/other_user}","gists_url":"https://api.github.com/users/hack4impact/gists{/gist_id}","starred_url":"https://api.github.com/users/hack4impact/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hack4impact/subscriptions","organizations_url":"https://api.github.com/users/hack4impact/orgs","repos_url":"https://api.github.com/users/hack4impact/repos","events_url":"https://api.github.com/users/hack4impact/events{/privacy}","received_events_url":"https://api.github.com/users/hack4impact/received_events","type":"Organization","site_admin":false},"repo":{"id":51207396,"name":"maps4all","full_name":"hack4impact/maps4all","owner":{"login":"hack4impact","id":9021093,"avatar_url":"https://avatars.githubusercontent.com/u/9021093?v=3","gravatar_id":"","url":"https://api.github.com/users/hack4impact","html_url":"https://github.com/hack4impact","followers_url":"https://api.github.com/users/hack4impact/followers","following_url":"https://api.github.com/users/hack4impact/following{/other_user}","gists_url":"https://api.github.com/users/hack4impact/gists{/gist_id}","starred_url":"https://api.github.com/users/hack4impact/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hack4impact/subscriptions","organizations_url":"https://api.github.com/users/hack4impact/orgs","repos_url":"https://api.github.com/users/hack4impact/repos","events_url":"https://api.github.com/users/hack4impact/events{/privacy}","received_events_url":"https://api.github.com/users/hack4impact/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hack4impact/maps4all","description":"Generalized application for displaying location-based resources on a map","fork":false,"url":"https://api.github.com/repos/hack4impact/maps4all","forks_url":"https://api.github.com/repos/hack4impact/maps4all/forks","keys_url":"https://api.github.com/repos/hack4impact/maps4all/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hack4impact/maps4all/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hack4impact/maps4all/teams","hooks_url":"https://api.github.com/repos/hack4impact/maps4all/hooks","issue_events_url":"https://api.github.com/repos/hack4impact/maps4all/issues/events{/number}","events_url":"https://api.github.com/repos/hack4impact/maps4all/events","assignees_url":"https://api.github.com/repos/hack4impact/maps4all/assignees{/user}","branches_url":"https://api.github.com/repos/hack4impact/maps4all/branches{/branch}","tags_url":"https://api.github.com/repos/hack4impact/maps4all/tags","blobs_url":"https://api.github.com/repos/hack4impact/maps4all/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hack4impact/maps4all/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hack4impact/maps4all/git/refs{/sha}","trees_url":"https://api.github.com/repos/hack4impact/maps4all/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hack4impact/maps4all/statuses/{sha}","languages_url":"https://api.github.com/repos/hack4impact/maps4all/languages","stargazers_url":"https://api.github.com/repos/hack4impact/maps4all/stargazers","contributors_url":"https://api.github.com/repos/hack4impact/maps4all/contributors","subscribers_url":"https://api.github.com/repos/hack4impact/maps4all/subscribers","subscription_url":"https://api.github.com/repos/hack4impact/maps4all/subscription","commits_url":"https://api.github.com/repos/hack4impact/maps4all/commits{/sha}","git_commits_url":"https://api.github.com/repos/hack4impact/maps4all/git/commits{/sha}","comments_url":"https://api.github.com/repos/hack4impact/maps4all/comments{/number}","issue_comment_url":"https://api.github.com/repos/hack4impact/maps4all/issues/comments{/number}","contents_url":"https://api.github.com/repos/hack4impact/maps4all/contents/{+path}","compare_url":"https://api.github.com/repos/hack4impact/maps4all/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hack4impact/maps4all/merges","archive_url":"https://api.github.com/repos/hack4impact/maps4all/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hack4impact/maps4all/downloads","issues_url":"https://api.github.com/repos/hack4impact/maps4all/issues{/number}","pulls_url":"https://api.github.com/repos/hack4impact/maps4all/pulls{/number}","milestones_url":"https://api.github.com/repos/hack4impact/maps4all/milestones{/number}","notifications_url":"https://api.github.com/repos/hack4impact/maps4all/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hack4impact/maps4all/labels{/name}","releases_url":"https://api.github.com/repos/hack4impact/maps4all/releases{/id}","deployments_url":"https://api.github.com/repos/hack4impact/maps4all/deployments","created_at":"2016-02-06T15:20:01Z","updated_at":"2016-03-26T02:18:45Z","pushed_at":"2016-04-18T04:32:11Z","git_url":"git://github.com/hack4impact/maps4all.git","ssh_url":"git@github.com:hack4impact/maps4all.git","clone_url":"https://github.com/hack4impact/maps4all.git","svn_url":"https://github.com/hack4impact/maps4all","homepage":"","size":913,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":5,"forks":0,"open_issues":5,"watchers":0,"default_branch":"master"}},"base":{"label":"hack4impact:master","ref":"master","sha":"63ea1a0048f65bacf3976b0ecd68e18d9f862c80","user":{"login":"hack4impact","id":9021093,"avatar_url":"https://avatars.githubusercontent.com/u/9021093?v=3","gravatar_id":"","url":"https://api.github.com/users/hack4impact","html_url":"https://github.com/hack4impact","followers_url":"https://api.github.com/users/hack4impact/followers","following_url":"https://api.github.com/users/hack4impact/following{/other_user}","gists_url":"https://api.github.com/users/hack4impact/gists{/gist_id}","starred_url":"https://api.github.com/users/hack4impact/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hack4impact/subscriptions","organizations_url":"https://api.github.com/users/hack4impact/orgs","repos_url":"https://api.github.com/users/hack4impact/repos","events_url":"https://api.github.com/users/hack4impact/events{/privacy}","received_events_url":"https://api.github.com/users/hack4impact/received_events","type":"Organization","site_admin":false},"repo":{"id":51207396,"name":"maps4all","full_name":"hack4impact/maps4all","owner":{"login":"hack4impact","id":9021093,"avatar_url":"https://avatars.githubusercontent.com/u/9021093?v=3","gravatar_id":"","url":"https://api.github.com/users/hack4impact","html_url":"https://github.com/hack4impact","followers_url":"https://api.github.com/users/hack4impact/followers","following_url":"https://api.github.com/users/hack4impact/following{/other_user}","gists_url":"https://api.github.com/users/hack4impact/gists{/gist_id}","starred_url":"https://api.github.com/users/hack4impact/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hack4impact/subscriptions","organizations_url":"https://api.github.com/users/hack4impact/orgs","repos_url":"https://api.github.com/users/hack4impact/repos","events_url":"https://api.github.com/users/hack4impact/events{/privacy}","received_events_url":"https://api.github.com/users/hack4impact/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hack4impact/maps4all","description":"Generalized application for displaying location-based resources on a map","fork":false,"url":"https://api.github.com/repos/hack4impact/maps4all","forks_url":"https://api.github.com/repos/hack4impact/maps4all/forks","keys_url":"https://api.github.com/repos/hack4impact/maps4all/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hack4impact/maps4all/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hack4impact/maps4all/teams","hooks_url":"https://api.github.com/repos/hack4impact/maps4all/hooks","issue_events_url":"https://api.github.com/repos/hack4impact/maps4all/issues/events{/number}","events_url":"https://api.github.com/repos/hack4impact/maps4all/events","assignees_url":"https://api.github.com/repos/hack4impact/maps4all/assignees{/user}","branches_url":"https://api.github.com/repos/hack4impact/maps4all/branches{/branch}","tags_url":"https://api.github.com/repos/hack4impact/maps4all/tags","blobs_url":"https://api.github.com/repos/hack4impact/maps4all/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hack4impact/maps4all/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hack4impact/maps4all/git/refs{/sha}","trees_url":"https://api.github.com/repos/hack4impact/maps4all/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hack4impact/maps4all/statuses/{sha}","languages_url":"https://api.github.com/repos/hack4impact/maps4all/languages","stargazers_url":"https://api.github.com/repos/hack4impact/maps4all/stargazers","contributors_url":"https://api.github.com/repos/hack4impact/maps4all/contributors","subscribers_url":"https://api.github.com/repos/hack4impact/maps4all/subscribers","subscription_url":"https://api.github.com/repos/hack4impact/maps4all/subscription","commits_url":"https://api.github.com/repos/hack4impact/maps4all/commits{/sha}","git_commits_url":"https://api.github.com/repos/hack4impact/maps4all/git/commits{/sha}","comments_url":"https://api.github.com/repos/hack4impact/maps4all/comments{/number}","issue_comment_url":"https://api.github.com/repos/hack4impact/maps4all/issues/comments{/number}","contents_url":"https://api.github.com/repos/hack4impact/maps4all/contents/{+path}","compare_url":"https://api.github.com/repos/hack4impact/maps4all/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hack4impact/maps4all/merges","archive_url":"https://api.github.com/repos/hack4impact/maps4all/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hack4impact/maps4all/downloads","issues_url":"https://api.github.com/repos/hack4impact/maps4all/issues{/number}","pulls_url":"https://api.github.com/repos/hack4impact/maps4all/pulls{/number}","milestones_url":"https://api.github.com/repos/hack4impact/maps4all/milestones{/number}","notifications_url":"https://api.github.com/repos/hack4impact/maps4all/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hack4impact/maps4all/labels{/name}","releases_url":"https://api.github.com/repos/hack4impact/maps4all/releases{/id}","deployments_url":"https://api.github.com/repos/hack4impact/maps4all/deployments","created_at":"2016-02-06T15:20:01Z","updated_at":"2016-03-26T02:18:45Z","pushed_at":"2016-04-18T04:32:11Z","git_url":"git://github.com/hack4impact/maps4all.git","ssh_url":"git@github.com:hack4impact/maps4all.git","clone_url":"https://github.com/hack4impact/maps4all.git","svn_url":"https://github.com/hack4impact/maps4all","homepage":"","size":913,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":5,"forks":0,"open_issues":5,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hack4impact/maps4all/pulls/27"},"html":{"href":"https://github.com/hack4impact/maps4all/pull/27"},"issue":{"href":"https://api.github.com/repos/hack4impact/maps4all/issues/27"},"comments":{"href":"https://api.github.com/repos/hack4impact/maps4all/issues/27/comments"},"review_comments":{"href":"https://api.github.com/repos/hack4impact/maps4all/pulls/27/comments"},"review_comment":{"href":"https://api.github.com/repos/hack4impact/maps4all/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hack4impact/maps4all/pulls/27/commits"},"statuses":{"href":"https://api.github.com/repos/hack4impact/maps4all/statuses/195e3d92be485b976cca733f45f31a7d835648e8"}}}}